From 097b261267a50710b2d44de32174904e541fc67b Mon Sep 17 00:00:00 2001 From: Jovan Djokic-Sumarac Date: Tue, 5 Aug 2025 20:18:11 +0200 Subject: [PATCH] add claude code and plug.lua --- README.md | 72 +++++++++++++++++++++++++++++ lua/keymap.lua | 25 ++++------ lua/lsp.lua | 48 ++++++------------- lua/pack.lua | 122 +++++++++++++++++++++++++++++++++++++++++++++++++ lua/plug.lua | 102 ++++++++++++++++++----------------------- 5 files changed, 264 insertions(+), 105 deletions(-) create mode 100644 README.md create mode 100644 lua/pack.lua diff --git a/README.md b/README.md new file mode 100644 index 0000000..4dc03da --- /dev/null +++ b/README.md @@ -0,0 +1,72 @@ +# Neovim Configuration + +A modern, minimal Neovim configuration built around Neovim's native package management with custom plugin handling. + +## Features + +- **Native Package Management**: Uses Neovim's built-in `vim.pack` for plugin management +- **Custom Plugin System**: Custom `pack.lua` module for simplified plugin configuration +- **Modern UI**: Catppuccin colorscheme with transparency and custom color overrides +- **LSP Integration**: Full Language Server Protocol support with Mason for easy installation +- **Smart Completion**: Blink.cmp for fast, intelligent autocompletion +- **Efficient Navigation**: Mini.pick for fuzzy finding, Oil.nvim for file management +- **Syntax Highlighting**: Treesitter with support for multiple languages + +## Plugin Highlights + +- **Colorscheme**: Catppuccin (Macchiato flavor) with custom transparency +- **LSP**: Mason + nvim-lspconfig for language servers +- **Completion**: Blink.cmp with snippet support +- **File Management**: Oil.nvim for directory editing +- **Status Line**: Lualine with clean separators +- **Development**: Claude Code integration for AI assistance + +## pack.lua + +`pack.lua` is a custom plugin management wrapper that bridges the gap between modern plugin managers (like lazy.nvim) and Neovim's native package system. It provides: + +### Key Features +- **Lazy.nvim-compatible syntax**: Write plugin specs similar to lazy.nvim +- **Dependency resolution**: Automatically handles nested plugin dependencies +- **Auto-setup**: Automatically calls `setup()` functions with provided options +- **URL flexibility**: Supports various URL formats and naming conventions + +### Use Case +Perfect for users who want the simplicity of native Neovim package management without sacrificing the convenience of modern plugin configuration patterns. Instead of manually managing `vim.pack.add()` calls and setup functions, you can define plugins declaratively: + +```lua +local plugins = { + 'https://github.com/catppuccin/nvim', + + { url = 'https://github.com/echasnovski/mini.pick', + setup = true }, + + { url = 'https://github.com/nvim-lualine/lualine.nvim', + dependencies = { 'https://github.com/nvim-tree/nvim-web-devicons' }, + setup = function() + require('lualine').setup({ /* config */ }) + end } +} +``` + +The module handles the complexity of dependency ordering, plugin loading, and setup calls automatically. + +## Key Bindings + +- **Leader**: `` +- **File Navigation**: `ff` (files), `e` (Oil) +- **LSP**: `gd` (hover), `lf` (format) +- **Terminal**: `tt` (new terminal) +- **Claude Code**: `cc` (toggle AI assistant) + +## Configuration Structure + +``` +lua/ +├── colors.lua # Catppuccin theme configuration +├── keymap.lua # Key mappings +├── lsp.lua # LSP and completion setup +├── options.lua # Vim options and settings +├── pack.lua # Custom plugin management system +└── plug.lua # Plugin definitions and setup +``` diff --git a/lua/keymap.lua b/lua/keymap.lua index fa22e07..9b84585 100644 --- a/lua/keymap.lua +++ b/lua/keymap.lua @@ -8,8 +8,8 @@ vim.keymap.set('t', '', '', { noremap = true }) vim.keymap.set('n', '', 'bprev', { noremap = true }) -- Move selected text up/down in visual mode -vim.keymap.set('v', 'J', ":m '>+1gv=gv", { noremap = true }) -vim.keymap.set('v', 'K', ":m '<-2gv=gv", { noremap = true }) +vim.keymap.set('v', 'J', "m '>+1gv=gv", { noremap = true }) +vim.keymap.set('v', 'K', "m '<-2gv=gv", { noremap = true }) -- Keep cursor in the middle when jumping or joining lines vim.keymap.set('n', 'J', 'mzJ`z', { noremap = true }) @@ -18,24 +18,19 @@ vim.keymap.set('n', '', 'zz', { noremap = true }) vim.keymap.set('n', 'n', 'nzzzv', { noremap = true }) vim.keymap.set('n', 'N', 'Nzzzv', { noremap = true }) --- Interface with system clipboard in normal, visual, and select modes -vim.keymap.set({ 'n', 'v', 'x' }, 'y', '\'+y', { noremap = true, silent = true }) -vim.keymap.set({ 'n', 'v', 'x' }, 'Y', '\'+yy', { noremap = true, silent = true }) -vim.keymap.set({ 'n', 'v', 'x' }, 'p', '\'+p', { noremap = true, silent = true }) - - -vim.keymap.set('n', 'ff', ':Pick files') -vim.keymap.set('n', 'fb', ':Pick buffers') -vim.keymap.set('n', 'h', ':Pick help') -vim.keymap.set('n', 'e', ':Oil') +vim.keymap.set('n', 'ff', 'Pick files') +vim.keymap.set('n', 'fb', 'Pick buffers') +vim.keymap.set('n', 'h', 'Pick help') +vim.keymap.set('n', 'e', 'Oil') vim.keymap.set('n', 'lf', vim.lsp.buf.format) -vim.keymap.set('n', 'o', ':update :source') -vim.keymap.set('n', 'w', ':write') -vim.keymap.set('n', 'q', ':quit') +vim.keymap.set('n', 'o', 'update source') +vim.keymap.set('n', 'w', 'write') +vim.keymap.set('n', 'q', 'quit') vim.keymap.set({ 'n', 'v', 'x' }, 'y', "'+y") vim.keymap.set({ 'n', 'v', 'x' }, 'd', "'+d") +vim.keymap.set('n', 'cc', 'ClaudeCode', { desc = 'Toggle Claude Code' }) diff --git a/lua/lsp.lua b/lua/lsp.lua index 244556f..4b5becf 100644 --- a/lua/lsp.lua +++ b/lua/lsp.lua @@ -1,22 +1,18 @@ -local configs = require('nvim-treesitter.configs') - -configs.setup({ +require('nvim-treesitter.configs').setup({ ensure_installed = { 'c', 'bash', 'c_sharp', - 'fennel', 'go', 'haskell', 'lua', 'python', - 'query', 'rust', 'vim', 'vimdoc', 'hyprlang', }, - sync_install = false, + sync_install = true, auto_install = true, highlight = { enable = true, @@ -26,47 +22,33 @@ configs.setup({ vim.filetype.add({ pattern = { ['.*/hypr/.*%.conf'] = 'hyprlang', - }, -}) - -vim.filetype.add({ - pattern = { ['*.tex'] = 'latex', }, }) -local mason = require("mason") -mason.setup() -local mason_lspconfig = require("mason-lspconfig") -mason_lspconfig.setup({ +require("mason").setup() +require("mason-lspconfig").setup({ ensure_installed = { - "fennel_ls", "lua_ls", "pylsp", "ltex", - "zls", - "rust_analyzer", }, automatic_installation = true, }) --- vim.api.nvim_create_autocmd('LspAttach', { --- callback = function(ev) --- local client = 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 }) --- end --- end, --- }) --- vim.cmd('set completeopt+=noselect') --- -require 'nvim-treesitter.configs'.setup({ - ensure_installed = { 'lua' }, - highlight = { enable = true } -}) -vim.lsp.enable({ 'lua_ls' }) +-- vim.lsp.config( 'lua_ls', { +-- settings = { +-- Lua = { +-- workspace = { +-- library = vim.api.nvim_get_runtime_file("", true) +-- } +-- } +-- } +-- }) +vim.lsp.config( 'lua_ls', { }) +vim.lsp.enable({ 'lua_ls', 'pylsp' }) require "blink.cmp".setup({ diff --git a/lua/pack.lua b/lua/pack.lua new file mode 100644 index 0000000..8b47a12 --- /dev/null +++ b/lua/pack.lua @@ -0,0 +1,122 @@ +local M = {} + +local function process_plugin(plugin) + local processed = {} + + -- Handle when plugin is just a string (URL) + if type(plugin) == "string" then + processed.url = plugin + return processed + end + + -- Handle the plugin URL/name (convert from lazy.nvim format) + if plugin[1] then + processed.url = plugin[1] + elseif plugin.url then + processed.url = plugin.url + elseif plugin.src then + processed.url = plugin.src + end + + -- Handle version + if plugin.version then + processed.version = plugin.version + end + + -- Handle opts (will be passed to setup function) + if plugin.opts then + processed.opts = plugin.opts + end + + -- Handle setup function + if plugin.setup then + if plugin.setup == true then + -- Auto-generate setup function from URL + local module_name = processed.url:match("([^/]+)%.nvim$") or processed.url:match("([^/]+)$") + if module_name and module_name:match("%.nvim$") then + module_name = module_name:gsub("%.nvim$", "") + end + processed.setup = function(opts) + if opts then + require(module_name).setup(opts) + else + require(module_name).setup() + end + end + else + processed.setup = plugin.setup + end + end + + return processed +end + +local function flatten_dependencies(deps) + local result = {} + + local function flatten(dep_list) + for _, dep in ipairs(dep_list) do + local processed_dep = process_plugin(dep) + table.insert(result, processed_dep) + + -- Recursively flatten nested dependencies + if dep.dependencies then + flatten(dep.dependencies) + end + end + end + + if deps then + flatten(deps) + end + + return result +end + +function M.setup(plugins) + local all_plugins = {} + + -- Process each plugin in the input table + for _, plugin in ipairs(plugins) do + local processed_plugin = process_plugin(plugin) + + -- Handle dependencies + if plugin.dependencies then + local deps = flatten_dependencies(plugin.dependencies) + for _, dep in ipairs(deps) do + table.insert(all_plugins, dep) + end + end + + table.insert(all_plugins, processed_plugin) + end + + -- Convert to vim.pack format and add plugins + local pack_plugins = {} + for _, plugin in ipairs(all_plugins) do + local pack_plugin = { + src = plugin.url, + } + + if plugin.version then + pack_plugin.version = plugin.version + end + + table.insert(pack_plugins, pack_plugin) + end + + vim.pack.add(pack_plugins) + + -- Handle setup calls after all plugins are added + for _, plugin in ipairs(all_plugins) do + if plugin.setup and type(plugin.setup) == "function" then + if plugin.opts then + plugin.setup(plugin.opts) + else + plugin.setup() + end + end + end +end + +return M diff --git a/lua/plug.lua b/lua/plug.lua index b871fb3..370dfbc 100644 --- a/lua/plug.lua +++ b/lua/plug.lua @@ -1,53 +1,54 @@ +local pack = require 'pack' + local plugins = { - { src = 'https://github.com/catppuccin/nvim' }, - { src = 'https://github.com/echasnovski/mini.cursorword' }, - { src = 'https://github.com/echasnovski/mini.pick' }, - { src = 'https://github.com/echasnovski/mini.starter' }, - { src = 'https://github.com/echasnovski/mini.trailspace' }, - { src = 'https://github.com/nvim-treesitter/nvim-treesitter' }, - { src = 'https://github.com/stevearc/oil.nvim' }, - { src = 'https://github.com/svampkorg/moody.nvim' }, + 'https://github.com/catppuccin/nvim', + 'https://github.com/nvim-treesitter/nvim-treesitter', - { src = 'https://github.com/nvim-lualine/lualine.nvim', - deps = { { src = 'https://github.com/nvim-tree/nvim-web-devicons' } }}, + { url = 'https://github.com/echasnovski/mini.cursorword', + setup = true }, - { src = 'https://github.com/williamboman/mason.nvim', - deps = { { src = 'https://github.com/williamboman/mason-lspconfig.nvim', - { src = 'https://github.com/neovim/nvim-lspconfig' }} }}, + { url = 'https://github.com/echasnovski/mini.pick', + setup = true }, - { src = 'https://github.com/Saghen/blink.cmp', - version = "v1.6.0", - deps = { { src = 'https://github.com/rafamadriz/friendly-snippets' } }}, + { url = 'https://github.com/echasnovski/mini.starter', + setup = true }, + + { url = 'https://github.com/echasnovski/mini.trailspace', + setup = true }, + + { url = 'https://github.com/stevearc/oil.nvim', + setup = true }, + + { url = 'https://github.com/svampkorg/moody.nvim', + setup = true }, + + { url = 'https://github.com/greggh/claude-code.nvim', + setup = true }, + + { url = 'https://github.com/nvim-lualine/lualine.nvim', + dependencies = { 'https://github.com/nvim-tree/nvim-web-devicons' }, + setup = function() + require('lualine').setup({ + options = { + section_separators = { left = '', right = '' }, + component_separators = { left = '', right = '' }, + } + }) + end }, + + { url = 'https://github.com/williamboman/mason.nvim', + dependencies = { + { url = 'https://github.com/williamboman/mason-lspconfig.nvim', setup = true }, + 'https://github.com/neovim/nvim-lspconfig' + }, + setup = true }, + + { url = 'https://github.com/Saghen/blink.cmp', + version = "v1.6.0", + dependencies = { 'https://github.com/rafamadriz/friendly-snippets' }}, } -local function flatten_plugins(plugins) - local result = {} - - local function flatten(t) - for _, plugin in ipairs(t) do - -- Copy plugin to avoid modifying original input - local p = {} - for k, v in pairs(plugin) do - if k ~= "deps" then - p[k] = v - end - end - table.insert(result, p) - - -- If there are dependencies, flatten them recursively - if plugin.deps then - flatten(plugin.deps) - end - end - end - - flatten(plugins) - return result -end - -local plugs = flatten_plugins(plugins) - -vim.pack.add(plugs) +pack.setup(plugins) @@ -90,18 +91,5 @@ for _, plug in ipairs(default_plugins) do end -require 'mini.pick'.setup() -require 'mini.cursorword'.setup() -require 'mini.starter'.setup() -require 'mini.trailspace'.setup() -require 'moody'.setup() -require 'oil'.setup() -require('lualine').setup({ - options = { - section_separators = { left = '', right = '' }, - component_separators = { left = '', right = '' }, - } -}) -