summaryrefslogtreecommitdiffstats
path: root/plugin
diff options
context:
space:
mode:
authorThomas Vanbesien <tvanbesi@proton.me>2026-05-04 08:44:50 +0200
committerThomas Vanbesien <tvanbesi@proton.me>2026-05-06 16:43:16 +0200
commit34510ebc63ff65d51f6979a86169bfc52de6180c (patch)
tree36c8b73c99a3c566ccee888818c60204398991fd /plugin
downloadnvim-config-34510ebc63ff65d51f6979a86169bfc52de6180c.tar.gz
nvim-config-34510ebc63ff65d51f6979a86169bfc52de6180c.zip
feat: initial setup
- `dotfiles` (this project's CLI) - foot configuration - tmux configuration - bash configuration - nvim (as a git submodule) + configuration - ranger configuration - fzf configuration - KDE global shortcuts - Other miscellaneous dependencies
Diffstat (limited to 'plugin')
-rw-r--r--plugin/10-treesitter.lua37
-rw-r--r--plugin/50-autoformat.lua24
-rw-r--r--plugin/50-autopairs.lua17
-rw-r--r--plugin/50-colors.lua99
-rw-r--r--plugin/50-completion.lua72
-rw-r--r--plugin/50-dap.lua28
-rw-r--r--plugin/50-dotfiles.lua36
-rw-r--r--plugin/50-fold.lua22
-rw-r--r--plugin/50-ftdetect.lua18
-rw-r--r--plugin/50-highlight.lua101
-rw-r--r--plugin/50-local.lua8
-rw-r--r--plugin/50-lorem.lua35
-rw-r--r--plugin/50-lsp.lua90
-rw-r--r--plugin/50-netrw.lua25
-rw-r--r--plugin/50-session.lua69
-rw-r--r--plugin/50-spell.lua34
-rw-r--r--plugin/50-statusline.lua48
17 files changed, 763 insertions, 0 deletions
diff --git a/plugin/10-treesitter.lua b/plugin/10-treesitter.lua
new file mode 100644
index 0000000..4602519
--- /dev/null
+++ b/plugin/10-treesitter.lua
@@ -0,0 +1,37 @@
+--
+-- Treesitter parsers
+--
+
+vim.pack.add({ "https://github.com/nvim-treesitter/nvim-treesitter" })
+
+require("nvim-treesitter").install({
+ "bash",
+ "diff",
+ "gitcommit",
+ "ini",
+ "json",
+ "lua",
+ "markdown",
+ "markdown_inline",
+ "readline",
+ "vim",
+ "vimdoc",
+})
+
+-- Parse the tree as early as possible, which is as soon as we know the filetype
+--
+-- Event handlers for the same event are triggered in the order they were created. This must be the first FileType
+-- handler created so that the tree is parsed for other FileType handlers (which often need the parsed tree). To create
+-- it first put this in a file that comes before alphabetically in the `plugin/` directory.
+vim.api.nvim_create_autocmd("FileType", {
+ desc = "Start treesitter",
+ group = vim.g.dotfiles.augroup,
+ callback = function()
+ local parser = vim.treesitter.get_parser(0)
+ if parser == nil then
+ return
+ end
+ parser:parse() -- Parse once asynchronously; used by logic that needs the parsed tree (like extmarks)
+ vim.treesitter.start()
+ end,
+})
diff --git a/plugin/50-autoformat.lua b/plugin/50-autoformat.lua
new file mode 100644
index 0000000..4761097
--- /dev/null
+++ b/plugin/50-autoformat.lua
@@ -0,0 +1,24 @@
+--
+-- Autoformat plugin
+--
+
+local function toggle_autoformat()
+ vim.b.autoformat = not vim.b.autoformat
+end
+
+-- Autoformat
+vim.api.nvim_create_autocmd("BufWritePre", {
+ desc = "Autoformat buffer",
+ group = vim.g.dotfiles.augroup,
+ callback = function(ev)
+ if vim.b.autoformat then
+ if vim.b.format_func == nil then
+ vim.notify("No formatter set for " .. ev.file .. " (" .. vim.o.filetype .. ")", vim.log.levels.WARN)
+ return
+ end
+ vim.b.format_func()
+ end
+ end,
+})
+
+vim.api.nvim_create_user_command("AutoformatToggle", toggle_autoformat, { desc = "Toggle autoformatting" })
diff --git a/plugin/50-autopairs.lua b/plugin/50-autopairs.lua
new file mode 100644
index 0000000..2ab41c8
--- /dev/null
+++ b/plugin/50-autopairs.lua
@@ -0,0 +1,17 @@
+--
+-- Autopairs configuration (inserting matching delimiters while inserting)
+--
+-- See https://github.com/windwp/nvim-autopairs
+
+vim.pack.add({ "https://github.com/windwp/nvim-autopairs" })
+
+local Rule = require("nvim-autopairs.rule")
+local npairs = require("nvim-autopairs")
+local cond = require("nvim-autopairs.conds")
+
+npairs.setup()
+
+npairs.add_rules({
+ Rule("*", "*", "markdown"):with_cr(cond.none()),
+ Rule("~", "~", "markdown"):with_cr(cond.none()),
+})
diff --git a/plugin/50-colors.lua b/plugin/50-colors.lua
new file mode 100644
index 0000000..f713a74
--- /dev/null
+++ b/plugin/50-colors.lua
@@ -0,0 +1,99 @@
+--
+-- Color scheme plugin
+--
+vim.pack.add({ "https://github.com/maxmx03/solarized.nvim" }) -- Solarized color scheme
+
+local solarized_colors = {
+ base03 = "#002b36",
+ base02 = "#073642",
+ base01 = "#586e75",
+ base00 = "#657b83",
+ base0 = "#839496",
+ base1 = "#93a1a1",
+ base2 = "#eee8d5",
+ base3 = "#fdf6e3",
+ yellow = "#b58900",
+ orange = "#cb4b16",
+ red = "#dc322f",
+ magenta = "#d33682",
+ violet = "#6c71c4",
+ blue = "#268bd2",
+ cyan = "#2aa198",
+ green = "#859900",
+}
+
+local function adjust_highlight()
+ if vim.g.colors_name == "solarized" then
+ -- General highlight
+ vim.api.nvim_set_hl(0, "EndOfBuffer", { fg = solarized_colors.base0, update = true })
+ vim.api.nvim_set_hl(0, "MatchParen", { link = "CurSearch" })
+ if vim.o.background == "light" then
+ vim.api.nvim_set_hl(0, "TabLineSel", { bg = "#edffd5" })
+ vim.api.nvim_set_hl(0, "Cursorline", { bg = "#edffd5" })
+ vim.api.nvim_set_hl(0, "NormalFloat", { bg = solarized_colors.base2 })
+ elseif vim.o.background == "dark" then
+ vim.api.nvim_set_hl(0, "TabLineSel", { bg = "#043624" })
+ vim.api.nvim_set_hl(0, "Cursorline", { bg = "#043624" })
+ vim.api.nvim_set_hl(0, "NormalFloat", { bg = solarized_colors.base02 })
+ end
+
+ -- Markdown highlight
+ if vim.o.background == "light" then
+ vim.api.nvim_set_hl(0, "@markup.raw", { bg = solarized_colors.base2, update = true })
+ elseif vim.o.background == "dark" then
+ vim.api.nvim_set_hl(0, "@markup.raw", { bg = solarized_colors.base02, update = true })
+ end
+ vim.api.nvim_set_hl(0, "@markup.raw.block", { fg = solarized_colors.cyan, update = true })
+ vim.api.nvim_set_hl(0, "@markup.heading.1", { link = "@markup.heading" })
+ vim.api.nvim_set_hl(0, "@markup.heading.2", { link = "@markup.heading" })
+ vim.api.nvim_set_hl(0, "@markup.heading.3", { link = "@markup.heading" })
+ vim.api.nvim_set_hl(0, "@markup.heading.4", { link = "@markup.heading" })
+ vim.api.nvim_set_hl(0, "@markup.heading.5", { link = "@markup.heading" })
+ vim.api.nvim_set_hl(0, "@markup.heading.6", { link = "@markup.heading" })
+ end
+end
+
+local function next_colorscheme()
+ local colorschemes = vim.fn.getcompletion("", "color")
+ vim.g.colors_name = vim.g.colors_name or "default"
+ for i = 1, #colorschemes do
+ if colorschemes[i] == vim.g.colors_name then
+ vim.cmd.colorscheme(colorschemes[(i % #colorschemes) + 1])
+ vim.notify("Color scheme set to " .. vim.g.colors_name)
+ return
+ end
+ end
+end
+
+local function random_colorscheme()
+ local colorschemes = vim.fn.getcompletion("", "color")
+ vim.cmd.colorscheme(colorschemes[math.random(#colorschemes)])
+ vim.notify("Color scheme set to " .. vim.g.colors_name)
+end
+
+local function toggle_theme()
+ vim.opt.background = vim.o.background == "light" and "dark" or "light"
+ vim.notify("Color theme set to " .. vim.o.background)
+end
+
+-- Adjust colors after the color scheme has loaded
+vim.api.nvim_create_autocmd("ColorScheme", {
+ desc = "Adjust color scheme",
+ group = vim.g.dotfiles.augroup,
+ callback = adjust_highlight,
+})
+
+-- Adjust colors when the theme (light/dark) changes
+vim.api.nvim_create_autocmd("OptionSet", {
+ desc = "Adjust color scheme",
+ pattern = "background",
+ group = vim.g.dotfiles.augroup,
+ callback = adjust_highlight,
+})
+
+vim.cmd.colorscheme("solarized") -- Default colorscheme
+vim.opt.background = "dark" -- Default theme
+
+vim.api.nvim_create_user_command("ColorsNext", next_colorscheme, { desc = "Load next color scheme" })
+vim.api.nvim_create_user_command("ColorsRandom", random_colorscheme, { desc = "Load random color scheme" })
+vim.api.nvim_create_user_command("ColorsThemeToggle", toggle_theme, { desc = "Toggle light/dark theme" })
diff --git a/plugin/50-completion.lua b/plugin/50-completion.lua
new file mode 100644
index 0000000..94b4cbb
--- /dev/null
+++ b/plugin/50-completion.lua
@@ -0,0 +1,72 @@
+--
+-- Completion configuration plugin
+--
+
+------------------------------------------------------------------------------------------------------------------------
+-- Insert mode completion
+------------------------------------------------------------------------------------------------------------------------
+-- See `:help ins-completion-menu`
+
+vim.opt.autocomplete = true -- Show completion menu automatically
+vim.opt.completeopt = {
+ "noselect", -- No item selected initially
+ "fuzzy",
+ "menuone", -- Show matches in a menu, even if there's only one match
+ "popup", -- Menu items show extra ingo in the popup window
+ "preview", -- Show extra info in the preview window
+}
+-- Completion sources (in order of priority)
+vim.opt.complete = {
+ "o", -- 'omnifunc'
+}
+vim.opt.pumwidth = 25
+vim.keymap.set("i", "<Tab>", function()
+ return vim.fn.pumvisible() == 1 and "<C-n>" or "<Tab>"
+end, { expr = true })
+vim.keymap.set("i", "<S-Tab>", function()
+ return vim.fn.pumvisible() == 1 and "<C-p>" or "<S-Tab>"
+end, { expr = true })
+
+------------------------------------------------------------------------------------------------------------------------
+-- Command-line mode completion
+------------------------------------------------------------------------------------------------------------------------
+-- See `:help cmdline-completion` and `:help cmdline-autocompletion`
+
+-- Show completion menu automatically
+vim.api.nvim_create_autocmd({ "CmdlineChanged", "CmdlineEnter" }, {
+ desc = "Autocompletion",
+ group = vim.g.dotfiles.augroup,
+ pattern = "[:\\/\\?]",
+ callback = function()
+ vim.cmd.call("wildtrigger()")
+ end,
+})
+vim.opt.wildmenu = true -- Show completions in a menu
+vim.opt.wildchar = 9 -- Char code assigned to command line wildcard expansion
+vim.opt.wildoptions = {
+ "exacttext", -- Discard regex artifacts when performing search pattern completion
+ "pum", -- Show completions in a popup menu
+ "tagfile", -- Show tag kind and file
+ "fuzzy", -- Fuzzy matching (doesn't work with files/dirs, see `:help 'wildoptions'`, but patterns do work!)
+}
+-- Completion modes triggered in order by `wildtrigger()` or 'wildchar'
+vim.opt.wildmode = {
+ "noselect", -- List matches without inserting
+ "full", -- List matches and insert first full match
+}
+-- Insert unique match
+vim.keymap.set("c", string.format("%c", vim.o.wildchar), function()
+ local complete_info = vim.fn.cmdcomplete_info()
+ if complete_info.pum_visible == 1 then
+ return #complete_info.matches == 1 and "<C-n><Space><BS>" or "<C-n>"
+ end
+ vim.fn.wildtrigger()
+end, { expr = true, desc = "Command line wildcard expansion" })
+-- Show next completion choices after accepting an entry with `<C-y>`
+vim.keymap.set("c", "<C-y>", function()
+ local complete_info = vim.fn.cmdcomplete_info()
+ if complete_info.pum_visible == 1 then
+ return complete_info.selected ~= -1 and "<Space><BS>" or "<C-e>"
+ end
+ return "<C-y>"
+end, { expr = true })
diff --git a/plugin/50-dap.lua b/plugin/50-dap.lua
new file mode 100644
index 0000000..683984c
--- /dev/null
+++ b/plugin/50-dap.lua
@@ -0,0 +1,28 @@
+--
+-- DAP client/adapter configurations
+--
+
+vim.pack.add({ "https://github.com/mfussenegger/nvim-dap" }) -- DAP (Debug Adapter Protocol) client
+local dap = require("dap")
+
+-- OSV configuration
+vim.pack.add({ "https://github.com/jbyuki/one-small-step-for-vimkind" }) -- DAP adapter for Neovim Lua
+local osv = require("osv")
+
+dap.configurations.lua = {
+ {
+ type = "nlua",
+ request = "attach",
+ name = "Attach to running Neovim instance",
+ },
+}
+dap.adapters.nlua = function(callback, config)
+ callback({ type = "server", host = config.host or "127.0.0.1", port = config.port or 8086 })
+end
+vim.api.nvim_create_user_command("OSVLaunch", function()
+ osv.launch({ port = 8086 })
+end, { desc = "Launch OSV server" })
+vim.api.nvim_create_user_command("OSVStatus", function()
+ vim.notify("OSV server running: " .. tostring(osv.is_running()))
+ vim.notify("OSV client attached: " .. tostring(osv.is_attached()))
+end, { desc = "Show OSV status" })
diff --git a/plugin/50-dotfiles.lua b/plugin/50-dotfiles.lua
new file mode 100644
index 0000000..122912c
--- /dev/null
+++ b/plugin/50-dotfiles.lua
@@ -0,0 +1,36 @@
+--
+-- dotfiles plugin
+--
+
+-- Returns true if the current buffer is part of the Dotfiles repository
+local function detect_dotfiles_file()
+ if vim.env.DOTFILES_DIR == nil then
+ return false
+ end
+ local ret = vim.system(
+ { "git", "--git-dir=" .. vim.env.DOTFILES_DIR, "--work-tree=" .. vim.env.HOME, "ls-files" },
+ { text = true }
+ ):wait()
+ local buf_file_name = string.sub(vim.api.nvim_buf_get_name(0), #vim.env.HOME + 2)
+ for _, dotfiles_filename in ipairs(vim.split(ret.stdout, "\n", { trimempty = true })) do
+ if dotfiles_filename == buf_file_name then
+ return true
+ end
+ end
+ return false
+end
+
+vim.api.nvim_create_autocmd("BufEnter", {
+ desc = "Detect dotfiles file",
+ group = vim.g.dotfiles.augroup,
+ callback = function()
+ vim.b.dotfiles_file = detect_dotfiles_file()
+ end,
+})
+
+vim.api.nvim_create_user_command("DotfilesOn", function()
+ vim.g.gitgutter_git_args = "--git-dir=" .. vim.env.DOTFILES_DIR .. " --work-tree=" .. vim.env.HOME
+end, { desc = "Activate dotfiles (set git env)" })
+vim.api.nvim_create_user_command("DotfilesOff", function()
+ vim.g.gitgutter_git_args = ""
+end, { desc = "Deactivate dotfiles (unset git env)" })
diff --git a/plugin/50-fold.lua b/plugin/50-fold.lua
new file mode 100644
index 0000000..c7013bb
--- /dev/null
+++ b/plugin/50-fold.lua
@@ -0,0 +1,22 @@
+--
+-- fold plugin
+--
+
+-- Initialize folds with foldmethod = expr if a treesitter parser is available, then switch back to manual
+-- This is to have the folds calculated and closed when editing the file initially, but with foldmethod set to manual
+-- Without foldmethod set to manual folds are created while writing in insert mode which is annoying
+--
+-- Skip floating windows, because they often are documentation (and thus should be visible by default)
+vim.api.nvim_create_autocmd("FileType", {
+ desc = "Initialize folds",
+ group = vim.g.dotfiles.augroup,
+ callback = function(ev)
+ if vim.api.nvim_win_get_config(0).relative ~= "" or vim.treesitter.get_parser(0) == nil then
+ return
+ end
+ vim.opt_local.foldexpr = "v:lua.vim.treesitter.foldexpr()"
+ vim.opt_local.foldmethod = "expr"
+ vim.cmd.normal({ "zX", bang = true })
+ vim.opt_local.foldmethod = "manual"
+ end,
+})
diff --git a/plugin/50-ftdetect.lua b/plugin/50-ftdetect.lua
new file mode 100644
index 0000000..49fc6d6
--- /dev/null
+++ b/plugin/50-ftdetect.lua
@@ -0,0 +1,18 @@
+--
+-- Filetype detection plugin
+--
+
+-- Detect bash files
+vim.api.nvim_create_autocmd({ "BufRead", "BufNewFile" }, {
+ desc = "Detect bash file",
+ group = vim.g.dotfiles.augroup,
+ pattern = "*",
+ callback = function()
+ if
+ string.find(vim.api.nvim_buf_get_name(0), "%.bash$")
+ or string.find(vim.api.nvim_buf_get_lines(0, 0, 1, false)[1] or "", "^#!/usr/bin/bash")
+ then
+ vim.bo.filetype = "bash"
+ end
+ end,
+})
diff --git a/plugin/50-highlight.lua b/plugin/50-highlight.lua
new file mode 100644
index 0000000..0e8fb97
--- /dev/null
+++ b/plugin/50-highlight.lua
@@ -0,0 +1,101 @@
+--
+-- Custom highlighting plugin (in `after/` to that the autocommand in `treesitter/init.lua` can be set first in order)
+--
+
+-- Returns an iterator over the ascendants of `node`, starting at the root node
+local function node_ascendants(node)
+ local root = node:tree():root()
+ local current = root
+ return function()
+ if current:equal(node) then
+ return nil
+ end
+ current = assert(current:child_with_descendant(node))
+ return current
+ end
+end
+
+-- Returns true if `node` or any of its parent has the type `type`
+local function node_within_type(node, type)
+ local next_ascendant = node_ascendants(node)
+ local next = next_ascendant()
+ while next do
+ if next:type() == type then
+ return true
+ end
+ next = next_ascendant()
+ end
+ return false
+end
+
+-- Returns an iterator over the positions (`{ col1, col2, row }`) of matches of pattern in lines
+local function pmatches(lines, pattern)
+ local col1, col2, row = nil, nil, 1
+ return function()
+ while row < #lines do
+ col1, col2 = string.find(lines[row], pattern, (col2 or 0) + 1)
+ if col1 then
+ return { col1 = col1, col2 = col2, row = row }
+ else
+ col1, col2, row = 0, 0, row + 1
+ end
+ end
+ return nil
+ end
+end
+
+-- Set extmarks are the positions (`{ col1, col2, row }`) given by `next_pos()`
+-- `opts`: {
+-- ns: highlight namespace
+-- predicate: is passed row and col, if true then set the mark
+-- hl_group: highlight group
+-- }
+local function set_extmarks(next_pos, opts)
+ for pos in next_pos do
+ local marks = vim.api.nvim_buf_get_extmarks(
+ 0,
+ opts.ns,
+ { pos.row - 1, pos.col1 - 1 },
+ { pos.row - 1, pos.col2 - 1 },
+ {}
+ )
+ if #marks == 0 and opts.predicate(pos.row - 1, pos.col1 - 1) then
+ vim.api.nvim_buf_set_extmark(
+ 0,
+ opts.ns,
+ pos.row - 1,
+ pos.col1 - 1,
+ { end_col = pos.col2, hl_group = opts.hl_group }
+ )
+ end
+ pos = next_pos()
+ end
+end
+
+-- TODO a better way to do this:
+-- For code, only check in "comment" node ranges
+-- For non-code, do it per type. For Markdown, only check "paragraph" nodes
+local function hl_todo_predicate(row, col)
+ if vim.o.filetype == "markdown" or vim.treesitter.get_parser() == nil then
+ return true
+ end
+ local node = assert(vim.treesitter.get_node({ pos = { row, col } }))
+ return node_within_type(node, "comment")
+end
+
+local patterns = { todo = "TODO" }
+local hl_ns = vim.api.nvim_create_namespace("extmarks")
+
+vim.api.nvim_set_hl(hl_ns, "dotfiles.Todo", { bg = "Yellow", fg = "Black", bold = true })
+local extmarks_todo_opts = { ns = hl_ns, hl_group = "dotfiles.Todo", predicate = hl_todo_predicate }
+
+-- Initialize extmarks
+vim.api.nvim_create_autocmd("FileType", {
+ desc = "Initialize extmarks",
+ group = vim.g.dotfiles.augroup,
+ callback = function()
+ vim.api.nvim_win_set_hl_ns(vim.api.nvim_get_current_win(), hl_ns)
+ local lines = vim.api.nvim_buf_get_lines(0, 0, -1, false)
+ set_extmarks(pmatches(lines, patterns.todo), extmarks_todo_opts)
+ end,
+})
diff --git a/plugin/50-local.lua b/plugin/50-local.lua
new file mode 100644
index 0000000..88c63c5
--- /dev/null
+++ b/plugin/50-local.lua
@@ -0,0 +1,8 @@
+--
+-- local include plugin
+--
+
+local local_config_file = vim.fn.stdpath("config") .. "/local.lua"
+if vim.uv.fs_stat(local_config_file) then
+ dofile(local_config_file)
+end
diff --git a/plugin/50-lorem.lua b/plugin/50-lorem.lua
new file mode 100644
index 0000000..8970574
--- /dev/null
+++ b/plugin/50-lorem.lua
@@ -0,0 +1,35 @@
+--
+-- Lorem plugin (command to insert "lorem ipsum" words)
+--
+
+-- Returns lorem ipsum words
+local function iter_lorem()
+ local filename = vim.env.HOME .. "/.local/share/dotfiles/lorem.txt"
+ local file = assert(io.open(filename, "r"))
+ local string = file:read("*all")
+ io.close(file)
+ local lorem_words = vim.split(vim.trim(string), " ", { trimempty = true })
+ local i = 0
+ return function()
+ i = i % #lorem_words + 1
+ return lorem_words[i]
+ end
+end
+
+-- Returns a n words long "lorem ipsum" string
+local function get_lorem(n)
+ local iter = iter_lorem()
+ local words = {}
+ for i = 1, n do
+ words[i] = iter()
+ end
+ return table.concat(words, " ")
+end
+
+local function put_lorem(n)
+ vim.api.nvim_put({ get_lorem(n) }, "c", true, true)
+end
+
+vim.api.nvim_create_user_command("Lorem", function(opts)
+ put_lorem(tonumber(opts.args))
+end, { desc = "Put lorem ipsum string", nargs = 1 })
diff --git a/plugin/50-lsp.lua b/plugin/50-lsp.lua
new file mode 100644
index 0000000..de86ecd
--- /dev/null
+++ b/plugin/50-lsp.lua
@@ -0,0 +1,90 @@
+--
+-- LSP client configurations
+--
+
+local function inspect_lsp()
+ local client = vim.lsp.get_clients()[1]
+ if client == nil then
+ vim.notify("No LSP client loaded")
+ return
+ end
+ vim.notify(vim.inspect(client.server_capabilities), vim.log.levels.INFO)
+end
+
+vim.pack.add({ "https://github.com/neovim/nvim-lspconfig" })
+
+vim.api.nvim_create_user_command("LspInspect", inspect_lsp, { desc = "Inpsect LSP client" })
+
+-- Enable LSP server capabilities if available when attaching, see `:help lsp-attach`
+vim.api.nvim_create_autocmd("LspAttach", {
+ desc = "Enable LSP capabilities",
+ group = vim.g.dotfiles.augroup,
+ callback = function(ev)
+ local client = assert(vim.lsp.get_client_by_id(ev.data.client_id))
+ if client:supports_method("textDocument/completion") then
+ vim.lsp.completion.enable(true, client.id, ev.buf, { autotrigger = true })
+ else
+ vim.notify("Client " .. client.name .. " does not support completion", vim.log.levels.WARN)
+ end
+ if client:supports_method("textDocument/inlayHint") then
+ vim.lsp.inlay_hint.enable(true, { bufnr = 0 })
+ else
+ vim.notify("Client " .. client.name .. " does not support inlay hints", vim.log.levels.WARN)
+ end
+ end,
+})
+
+vim.api.nvim_create_user_command("LspHintToggle", function()
+ vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled({ bufnr = 0 }), { bufnr = 0 })
+end, { desc = "Toggle LSP inlay hints" })
+
+------------------------------------------------------------------------------------------------------------------------
+-- Lua
+------------------------------------------------------------------------------------------------------------------------
+
+vim.lsp.config("lua_ls", {
+ on_init = function(client)
+ -- Use `.luarc.json` or `.luarc.jsonc` if available, then exit
+ -- See `:help vim.lsp.ClientConfig` for `workspace_folders`
+ if client.workspace_folders then
+ local path = client.workspace_folders[1].name
+ if
+ path ~= vim.fn.stdpath("config")
+ and (vim.uv.fs_stat(path .. "/.luarc.json") or vim.uv.fs_stat(path .. "/.luarc.jsonc"))
+ then
+ return
+ end
+ end
+ -- See Lua language server configuration settings at https://luals.github.io/wiki/settings
+ client.config.settings.Lua = vim.tbl_deep_extend("force", client.config.settings.Lua, {
+ runtime = {
+ version = "Lua 5.1",
+ path = { "?.lua", "?/init.lua" }, -- See `:h lua-module-load`
+ },
+ workspace = {
+ checkThirdParty = false,
+ library = vim.api.nvim_get_runtime_file("", true), -- Load all folders in 'runtimepath'
+ },
+ })
+ end,
+})
+vim.lsp.enable("lua_ls")
+
+------------------------------------------------------------------------------------------------------------------------
+-- Bash
+------------------------------------------------------------------------------------------------------------------------
+
+vim.lsp.enable("bashls")
+
+------------------------------------------------------------------------------------------------------------------------
+-- Markdown
+------------------------------------------------------------------------------------------------------------------------
+
+vim.lsp.config("marksman", { filetypes = { "markdown" } })
+vim.lsp.enable("marksman")
+
+------------------------------------------------------------------------------------------------------------------------
+-- Vimscript
+------------------------------------------------------------------------------------------------------------------------
+
+vim.lsp.enable("vimls")
diff --git a/plugin/50-netrw.lua b/plugin/50-netrw.lua
new file mode 100644
index 0000000..4fdbfa6
--- /dev/null
+++ b/plugin/50-netrw.lua
@@ -0,0 +1,25 @@
+--
+-- netrw plugin
+--
+
+local function explore()
+ local windows = vim.api.nvim_tabpage_list_wins(0)
+ for _, win in ipairs(windows) do
+ local buf = vim.api.nvim_win_get_buf(win)
+ local ft = vim.api.nvim_get_option_value("filetype", { buf = buf })
+ if ft == "netrw" then
+ if win ~= vim.api.nvim_get_current_win() then
+ vim.api.nvim_set_current_win(win)
+ return
+ end
+ break
+ end
+ end
+ vim.cmd.Lexplore()
+end
+
+vim.g.netrw_liststyle = 3 -- 3: list style
+vim.g.netrw_winsize = -30 -- 30 colums wide
+vim.g.netrw_banner = 0 -- No banner
+
+vim.api.nvim_create_user_command("GotoExplorer", explore, { desc = "Open/close/focus netrw window" })
diff --git a/plugin/50-session.lua b/plugin/50-session.lua
new file mode 100644
index 0000000..b4aadda
--- /dev/null
+++ b/plugin/50-session.lua
@@ -0,0 +1,69 @@
+--
+-- Session plugin
+--
+
+local session_dir = vim.fn.stdpath("state") .. "/sessions"
+local session_default = session_dir .. "/default.vim"
+if not vim.uv.fs_stat(session_dir) then
+ vim.uv.fs_mkdir(session_dir, tonumber("755", 8))
+ vim.notify("Sessions save directory created at " .. session_dir)
+end
+
+local function save_session(path)
+ vim.cmd.mksession({ path, bang = true })
+end
+
+local function load_session(path)
+ vim.cmd.source(path)
+end
+
+local function reload_session(path)
+ save_session(path)
+ vim.cmd.restart({ args = { "+qall", "SessionLoad", path } })
+end
+
+local function delete_session(path)
+ vim.fs.rm(path)
+end
+
+local function session_completefunc(arg_lead, _, _)
+ local completions = {}
+ for path in vim.fs.dir(session_dir) do
+ if string.match(path, "^" .. arg_lead) and string.match(path, ".vim$") then
+ completions[#completions + 1] = path:sub(1, -5)
+ end
+ end
+ return completions
+end
+
+local function session_op(base, op)
+ local path = #base > 0 and base or session_default
+ if not string.match(path, "^" .. session_dir) then
+ path = session_dir .. "/" .. path
+ end
+ if not string.match(path, "%.vim$") then
+ path = path .. ".vim"
+ end
+ op(path)
+end
+
+vim.api.nvim_create_user_command("SessionSave", function(ev)
+ session_op(ev.args, save_session)
+end, { desc = "Save session", nargs = "?", complete = session_completefunc })
+vim.api.nvim_create_user_command("SessionLoad", function(ev)
+ session_op(ev.args, load_session)
+end, { desc = "Load session", nargs = "?", complete = session_completefunc })
+vim.api.nvim_create_user_command("SessionDelete", function(ev)
+ session_op(ev.args, delete_session)
+end, { desc = "Delete session", nargs = "?", complete = session_completefunc })
+vim.api.nvim_create_user_command("SessionRestart", function(ev)
+ session_op(ev.args, reload_session)
+end, { desc = "Reload session", nargs = "?", complete = session_completefunc })
+vim.api.nvim_create_user_command("SessionExitSave", function(ev)
+ session_op(ev.args, save_session)
+ vim.cmd.qall()
+end, { desc = "Save and exit session", nargs = "?", complete = session_completefunc })
+vim.api.nvim_create_user_command("SessionExitNoSave", function(ev)
+ session_op(ev.args, save_session)
+ vim.cmd.qall({ bang = true })
+end, { desc = "Save and exit session", nargs = "?", complete = session_completefunc })
diff --git a/plugin/50-spell.lua b/plugin/50-spell.lua
new file mode 100644
index 0000000..56d4c5f
--- /dev/null
+++ b/plugin/50-spell.lua
@@ -0,0 +1,34 @@
+--
+-- Spell check plugin
+--
+
+local function toggle_spell()
+ vim.o.spell = not vim.o.spell
+end
+
+local function set_spell_en()
+ vim.opt.spelllang = { "en_us" }
+end
+
+local function set_spell_fr()
+ vim.opt.spelllang = { "fr" }
+end
+
+local function set_spell_en_fr()
+ vim.opt.spelllang = { "en_us", "fr" }
+end
+
+vim.opt.spelllang = "en_us" -- Initial spell language
+vim.opt.spellfile = { -- Spellfiles for zg, zw, z=, etc
+ "/home/tvanbesi/.config/nvim/spell/en.utf-8.add",
+ "/home/tvanbesi/.config/nvim/spell/fr.utf-8.add",
+}
+
+vim.api.nvim_create_user_command("SpellToggle", toggle_spell, { desc = "Toggle spell checking" })
+vim.api.nvim_create_user_command("SpellSetEn", set_spell_en, { desc = "Set spell language to English" })
+vim.api.nvim_create_user_command("SpellSetFr", set_spell_fr, { desc = "Set spell language to French" })
+vim.api.nvim_create_user_command(
+ "SpellSetEnFr",
+ set_spell_en_fr,
+ { desc = "Set spell languages to English and French" }
+)
diff --git a/plugin/50-statusline.lua b/plugin/50-statusline.lua
new file mode 100644
index 0000000..092f08f
--- /dev/null
+++ b/plugin/50-statusline.lua
@@ -0,0 +1,48 @@
+--
+-- Status line configuration plugin
+--
+-- I use lualine, see https://github.com/nvim-lualine/lualine.nvim#configuring-lualine-in-initvim
+
+vim.pack.add({
+ "https://github.com/nvim-tree/nvim-web-devicons",
+ "https://github.com/nvim-lualine/lualine.nvim",
+})
+local lualine = require("lualine")
+
+local function spell_status()
+ if vim.o.spelllang == "fr" then
+ return "+S(fr)"
+ elseif vim.o.spelllang == "en_us" then
+ return "+S(en)"
+ elseif vim.o.spelllang == "en_us,fr" then
+ return "+S(en,fr)"
+ end
+end
+
+local function statuses()
+ return (vim.b.autoformat and "+F" or "") .. (vim.o.spell and spell_status() or "")
+end
+
+local lualine_sections = {
+ lualine_c = { statuses, "filename" },
+ lualine_x = { "encoding", "fileformat", "filetype", "lsp_status" },
+}
+
+-- Adjust colors when the theme (light/dark) changes
+vim.api.nvim_create_autocmd("OptionSet", {
+ desc = "Adjust color scheme",
+ pattern = "background",
+ group = vim.g.dotfiles.augroup,
+ callback = function()
+ lualine.setup({
+ options = { theme = vim.o.background == "light" and "solarized_light" or "solarized_dark" },
+ sections = lualine_sections,
+ })
+ end,
+})
+
+lualine.setup({ options = { theme = "solarized_light" }, sections = lualine_sections })
+
+vim.api.nvim_create_user_command("LualineConfig", function()
+ vim.notify(vim.inspect(lualine.get_config()))
+end, { desc = "Show lualine configuration" })