From aa5717f00fd14430c80939a68d7107c26de6e554 Mon Sep 17 00:00:00 2001 From: Mohammad Reza Karimi Date: Tue, 20 Jan 2026 15:55:27 -0500 Subject: first commit --- lua/mo/blink.lua | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++ lua/mo/cmp.lua | 42 +++++++++++++++++ lua/mo/fzf.lua | 77 +++++++++++++++++++++++++++++++ lua/mo/kinds.lua | 27 +++++++++++ lua/mo/notif.lua | 8 ++++ lua/mo/oil-util.lua | 67 +++++++++++++++++++++++++++ lua/mo/statusline.lua | 20 ++++++++ lua/mo/zen.lua | 89 ++++++++++++++++++++++++++++++++++++ 8 files changed, 453 insertions(+) create mode 100644 lua/mo/blink.lua create mode 100644 lua/mo/cmp.lua create mode 100644 lua/mo/fzf.lua create mode 100644 lua/mo/kinds.lua create mode 100644 lua/mo/notif.lua create mode 100644 lua/mo/oil-util.lua create mode 100644 lua/mo/statusline.lua create mode 100644 lua/mo/zen.lua (limited to 'lua') diff --git a/lua/mo/blink.lua b/lua/mo/blink.lua new file mode 100644 index 0000000..ec68ec4 --- /dev/null +++ b/lua/mo/blink.lua @@ -0,0 +1,123 @@ +---@diagnostic disable: param-type-mismatch +---@diagnostic disable: missing-fields + +local M = {} + +M.setup = function() + require("blink.cmp").setup({ + keymap = { + preset = "default", + [""] = {}, + [""] = {}, + }, + completion = { + list = { selection = { preselect = false, auto_insert = true } }, + }, + snippets = { preset = "mini_snippets" }, + cmdline = { enabled = false }, + appearance = { + nerd_font_variant = "normal", + }, + sources = { + default = { "lsp", "path", "snippets", "buffer" }, + providers = { + buffer = { + min_keyword_length = function(ctx) + return ctx.trigger.initial_kind == "manual" and 0 or 3 + end, + opts = { get_bufnrs = vim.api.nvim_list_bufs }, + }, + snippets = { + should_show_items = function(ctx) + return ctx.trigger.initial_kind ~= "trigger_character" + end, + }, + }, + }, + fuzzy = { implementation = "prefer_rust" }, + signature = { enabled = true }, + }) +end + +---@param data string +---@param _opts { hl: string, status: "running"|"success"|"failed", id: (integer|string)?, fast: boolean } +---@return integer|string|nil +local function show_status(data, _opts) + local opts = vim.tbl_extend( + "keep", + _opts, + { hl = "Normal", status = "running", fast = false } + ) + local fn = function() + return vim.api.nvim_echo({ { data, opts.hl } }, false, { + id = opts.id, + kind = "progress", + title = "Building blink-cmp", + status = opts.status, + }) + end + if opts.fast then return fn() end + vim.schedule(fn) + return nil +end + +M.build_rust = function() + local blink_pack = vim.pack.get({ "blink.cmp" })[1] + if blink_pack == nil then return end + + local msg_id = show_status( + "Starting", + { hl = "Comment", status = "running", fast = true } + ) + + local uv = vim.uv + local stdout = uv.new_pipe() + local stderr = uv.new_pipe() + + local on_exit = function(code, signal) + show_status( + ("Finished build (code=%s, signal=%s)"):format(code, signal), + { + hl = "Comment", + status = code == 0 and "success" or "failed", + id = msg_id, + fast = false, + } + ) + end + + local on_stdout = function(err, data) + assert(not err, err) + if data then + show_status(data, { + hl = "Normal", + status = "running", + id = msg_id, + fast = false, + }) + end + end + + local on_stderr = function(err, data) + assert(not err, err) + if data then + show_status(data, { + hl = "Comment", + status = "running", + id = msg_id, + fast = false, + }) + end + end + + uv.spawn("cargo", { + args = { "build", "--release" }, + stdio = { nil, stdout, stderr }, + cwd = blink_pack.path, + }, on_exit) + + uv.read_start(stdout, on_stdout) + uv.read_start(stderr, on_stderr) +end + +return M diff --git a/lua/mo/cmp.lua b/lua/mo/cmp.lua new file mode 100644 index 0000000..be6fb95 --- /dev/null +++ b/lua/mo/cmp.lua @@ -0,0 +1,42 @@ +vim.cmd([[ packadd nvim-cmp ]]) + +local cmp = require("cmp") +local icons = require("mini.icons") +local kinds = require("mo.kinds") +local minisnippets = require("mini.snippets") + +cmp.setup({ + view = { entries = "native" }, + formatting = { + format = function(entry, vim_item) + if entry.source.name == "nvim_lsp" and vim_item.kind ~= nil then + local icon, _, _ = icons.get("lsp", vim_item.kind) + vim_item.kind = + string.format("%s %s", icon, kinds[vim_item.kind]) + end + return vim_item + end, + }, + snippet = { + expand = function(args) + local insert = minisnippets.config.expand.insert + or minisnippets.default_insert + insert({ body = args.body }) -- Insert at cursor + cmp.resubscribe({ "TextChangedI", "TextChangedP" }) + require("cmp.config").set_onetime({ sources = {} }) + end, + }, + mapping = cmp.mapping.preset.insert({ + [""] = cmp.mapping.scroll_docs(-4), + [""] = cmp.mapping.scroll_docs(4), + [""] = cmp.mapping.complete(), + [""] = cmp.mapping.abort(), + [""] = cmp.mapping.confirm({ select = true }), -- Accept currently selected item. Set `select` to `false` to only confirm explicitly selected items. + }), + sources = cmp.config.sources({ + { name = "nvim_lsp" }, + }, { + { name = "path" }, + { name = "buffer" }, + }), +}) diff --git a/lua/mo/fzf.lua b/lua/mo/fzf.lua new file mode 100644 index 0000000..c5c4b3e --- /dev/null +++ b/lua/mo/fzf.lua @@ -0,0 +1,77 @@ +--- @diagnostic disable: missing-fields +local fzf = require("fzf-lua") + +local swiper = { + previewer = "swiper", + winopts = function() + local height = math.ceil(vim.o.lines / 3) + return { split = ("botright %snew +set\\ nobl"):format(height) } + end, +} + +fzf.setup({ + { "default-title", "hide" }, + fzf_colors = true, + lsp = { + symbols = { symbol_style = 3 }, + document_symbols = swiper, + code_actions = { previewer = "codeaction_native" }, + }, + manpages = { previewer = "man_native" }, + helptags = { previewer = "help_native" }, + defaults = { git_icons = false, file_icons = false }, + tags = { previewer = "bat" }, + btags = { previewer = "bat" }, + files = { fzf_opts = { ["--ansi"] = false } }, + grep = { + fzf_opts = { ["--ansi"] = false }, + rg_glob = true, + rg_opts = " --color=never --column --line-number --no-heading --smart-case --max-columns=4096 -e", + }, + builtin = { winopts = { width = 1, height = 1 } }, + blines = swiper, + grep_curbuf = swiper, + treesitter = swiper, + git = { blame = swiper }, + + winopts = function() + local height = math.ceil(vim.o.lines / 2) + return { + backdrop = 80, + row = 1, + col = 0, + width = 1, + height = height > 3 and height or 1, + border = {"", " ", "", "", "", "", "", ""}, + toggle_behavior = "extend", + --- @diagnostic disable-next-line: missing-fields + preview = { + default = { "bat" }, + treesitter = false, + layout = "vertical", + vertical = "up:60%", + border = {"", " ", "", "", "", "", "", ""}, + }, + on_create = function() + vim.keymap.set( + "t", + "", + [['"'.nr2char(getchar()).'pi']], + { + expr = true, + buffer = true, + desc = "insert register value into the FZF prompt", + } + ) + end, + } + end, + keymap = { + fzf = { + ["ctrl-q"] = "select-all+accept", + }, + }, +}) + +_G.old_vim_ui_select = vim.ui.select +fzf.register_ui_select() diff --git a/lua/mo/kinds.lua b/lua/mo/kinds.lua new file mode 100644 index 0000000..b6d7814 --- /dev/null +++ b/lua/mo/kinds.lua @@ -0,0 +1,27 @@ +return { + Text = "Text", + Method = "Meth", + Function = "Func", + Constructor = "Cons", + Field = "Fld", + Variable = "Var", + Class = "Cls", + Interface = "Ifs", + Module = "Mod", + Property = "Prop", + Unit = "Unit", + Value = "Val", + Enum = "Enum", + Keyword = "Keyw", + Snippet = "Snp", + Color = "Col", + File = "File", + Reference = "Ref", + Folder = "Fold", + EnumMember = "EnMe", + Constant = "Cnst", + Struct = "Stru", + Event = "Ev", + Operator = "Op", + TypeParameter = "Typ", +} diff --git a/lua/mo/notif.lua b/lua/mo/notif.lua new file mode 100644 index 0000000..019afbd --- /dev/null +++ b/lua/mo/notif.lua @@ -0,0 +1,8 @@ +local M = {} + +M.err = function(e) vim.notify(e, vim.log.levels.ERROR) end +M.info = function(e) vim.notify(e, vim.log.levels.INFO) end +M.debug = function(e) vim.notify(e, vim.log.levels.DEBUG) end +M.warn = function(e) vim.notify(e, vim.log.levels.WARN) end + +return M diff --git a/lua/mo/oil-util.lua b/lua/mo/oil-util.lua new file mode 100644 index 0000000..1b00fa7 --- /dev/null +++ b/lua/mo/oil-util.lua @@ -0,0 +1,67 @@ +local M = {} + +local notif = require("mo.notif") + +---@param opts { full_path: boolean } +M.copy_to_clipboard = function(opts) + opts = opts or { full_path = true } + + local oil = require("oil") + local dir = oil.get_current_dir() + if not dir then + notif.err("System clipboard only works for local files") + return + end + + local entries = {} + local mode = vim.api.nvim_get_mode().mode + if mode == "v" or mode == "V" then + local start = vim.fn.getpos("v") + local end_ = vim.fn.getpos(".") + local start_row = start[2] + local end_row = end_[2] + + if start_row > end_row then + start_row, end_row = end_row, start_row + end + + for i = start_row, end_row do + table.insert(entries, oil.get_entry_on_line(0, i)) + end + + vim.api.nvim_feedkeys( + vim.api.nvim_replace_termcodes("", true, false, true), + "n", + true + ) + else + table.insert(entries, oil.get_cursor_entry()) + end + + -- This removes holes in the list-like table + entries = vim.tbl_values(entries) + + if #entries == 0 then + vim.notify( + "Could not find local file under cursor", + vim.log.levels.WARN + ) + return + end + local paths = {} + for _, entry in ipairs(entries) do + if opts.full_path then + table.insert(paths, dir .. entry.name) + else + table.insert(paths, entry.name) + end + end + require("vim.ui.clipboard.osc52").copy("+")(paths) + if #paths == 1 then + notif.info(string.format("Copied '%s' to system clipboard", paths[1])) + else + notif.info(string.format("Copied %d files to system clipboard", #paths)) + end +end + +return M diff --git a/lua/mo/statusline.lua b/lua/mo/statusline.lua new file mode 100644 index 0000000..b24436c --- /dev/null +++ b/lua/mo/statusline.lua @@ -0,0 +1,20 @@ +-- local function lsp_status() +-- local clients = vim.lsp.get_active_clients({ bufnr = 0 }) +-- if #clients == 0 then return "" end +-- local names = {} +-- for _, client in ipairs(clients) do +-- table.insert(names, client.name) +-- end +-- return "[" .. table.concat(names, ", ") .. "]" +-- end + +local M = {} + +function M.lsp_status() + local clients = vim.lsp.get_clients({ bufnr = 0 }) + if #clients == 0 then return "" end + + return "%#StatusLineLsp#[" .. table.concat(vim.tbl_map(function(client) return client.name end, clients), ",") .. "]%* " +end + +return M diff --git a/lua/mo/zen.lua b/lua/mo/zen.lua new file mode 100644 index 0000000..eb674ba --- /dev/null +++ b/lua/mo/zen.lua @@ -0,0 +1,89 @@ +local M = {} +M.themes = { + dark = { + "seoulbones", + "rosebones", + "forestbones", + "zenwritten", + }, + light = { + "seoulbones", + "vimbones", + "rosebones", + "forestbones", + }, +} +M.current = { + dark = 1, + light = 1, +} +M.bg = "dark" + +M.cycle = function() + M.current[M.bg] = M.current[M.bg] + 1 + if M.current[M.bg] > #M.themes[M.bg] then M.current[M.bg] = 1 end + M.set() +end + +M.set = function() + vim.o.background = M.bg + local theme = M.themes[M.bg][M.current[M.bg]] + vim.print("Switching to " .. theme) + + vim.g[theme .. "_compat"] = 1 + vim.cmd.colorscheme(theme) + + -- make strings nonitalic + local str_highlight = + vim.api.nvim_get_hl(0, { name = "String", link = false }) + vim.api.nvim_set_hl( + 0, + "String", + { fg = str_highlight.fg, italic = false, force = true } + ) + + -- make booleans nonitalic and bold + local bool_highlight = + vim.api.nvim_get_hl(0, { name = "Boolean", link = false }) + vim.api.nvim_set_hl( + 0, + "Boolean", + { fg = bool_highlight.fg, italic = false, bold = true, force = true } + ) + + -- make normals in seoulbones darker + if theme == "seoulbones" and M.bg == "dark" then + local norm_highlight = + vim.api.nvim_get_hl(0, { name = "Normal", link = false }) + vim.api.nvim_set_hl( + 0, + "Normal", + { fg = norm_highlight.fg, bg = "#313131", force = true } + ) + end +end + +M.togglebg = function() + M.bg = M.bg == "dark" and "light" or "dark" + M.set() +end + +---@param theme string? +---@param bg "dark"|"light"|nil +M.setup = function(theme, bg) + vim.cmd("packadd zenbones.nvim") + if bg then M.bg = bg end + if theme then + for i, th in ipairs(M.themes[M.bg]) do + if th == theme then + M.current[M.bg] = i + break + end + end + end + M.set() + vim.keymap.set("n", "", M.cycle, {}) + vim.keymap.set("n", "", M.togglebg, {}) +end + +return M -- cgit v1.2.3-71-gdd5e