-- -- This is the editor of a Real Coder. -- Not as clumsy as a bloated IDE. -- An elegant editor for a more civilized age. -- ― Bernie Innocenti, https://codewiz.org -- vim.api.nvim_create_user_command('Conf', 'split ~/.config/nvim/init.lua', {}) vim.api.nvim_create_user_command('VConf', 'vsplit ~/.config/nvim/init.lua', {}) vim.api.nvim_create_user_command('ConfReload', 'luafile ~/.config/nvim/init.lua', {}) -- Recommended by nvim-tree vim.g.loaded_netrw = 1 vim.g.loaded_netrwPlugin = 1 -- General options vim.opt.mouse = 'a' -- Enable mouse in all modes vim.opt.mousescroll = 'ver:3,hor:3' vim.opt.mousemoveevent = true vim.opt.autowriteall = true -- Write on :n, :r, etc. -- vim.opt.backupcopy = "auto,breakhardlink" -- Don't break symlinks (edit destination), but break hardlinks vim.opt.undofile = true -- Enable persistent undo. vim.opt.shada:append('f100') -- Save cursor position and marks -- vim.opt.shada = "'100,f100,h" vim.opt.suffixes:remove(".h") -- Don't sort header files at lower priority. -- UI options vim.opt.wrap = false -- Display long lines as just one line. vim.opt.updatetime = 500 -- Milliseconds for the CursorHold event vim.opt.cursorline = true vim.opt.colorcolumn = '+1' vim.opt.signcolumn = 'number' -- Use number column if present vim.opt.showmode = false -- Redundant with fancy status lines vim.opt.belloff = 'cursor' -- Leave bell enabled in some cases vim.opt.termguicolors = true vim.opt.list = true -- Show whitespace vim.opt.listchars = { nbsp = "⦸", -- CIRCLED REVERSE SOLIDUS (U+29B8, UTF-8: E2 A6 B8) extends = "»", -- RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK (U+00BB, UTF-8: C2 BB) precedes = "«", -- LEFT-POINTING DOUBLE ANGLE QUOTATION MARK (U+00AB, UTF-8: C2 AB) trail = "⸱", -- Word Separator Middle Dot } -- vim.opt.listchars:append "eol:↴" vim.opt.listchars:append "tab:˃ " vim.opt.showbreak = "↳ " -- DOWNWARDS ARROW WITH TIP RIGHTWARDS (U+21B3, UTF-8: E2 86 B3) -- vim.opt.conceallevel = 2 -- Hide (conceal) special symbols (like `` in markdown) vim.opt.splitbelow = true -- Horizontal splits will be below vim.opt.splitright = true -- Vertical splits will be to the right vim.opt.splitkeep = "screen" -- Recommended by edgy vim.opt.equalalways = false -- Don't resize other windows after splitting vim.opt.winminheight = 0 -- Pack horizontal splits more tightly vim.opt.shortmess:append('c') -- Completion messages vim.opt.shortmess:append('I') -- No version splash -- vim.opt.pumblend = 10 -- Pseudo-transparency for popup-menu -- Editing vim.opt.ignorecase = true -- Ignore case in searches. vim.opt.smartcase = true -- Don't ignore case in searches if uppercase characters present vim.opt.clipboard = { "unnamed", "unnamedplus" } -- Use system clipboard. vim.opt.completeopt = { "menu", "menuone", "noinsert", "popup" } vim.opt.matchpairs:append('<:>') -- Spelling vim.opt.spelloptions = "camel" -- Treat parts of camelCase words as seprate words. -- Indenting vim.opt.tabstop = 8 -- vim.opt.shiftwidth = 0 -- 0 means same as tabstop vim.opt.shiftround = true -- Round indent to multiples of 'shiftwidth' vim.opt.smartindent = true vim.api.nvim_create_autocmd('Filetype', { pattern = "c,cpp,java,rust,python,bzl", callback = function() vim.opt.shiftwidth = 4; vim.opt.expandtab = true end, }) vim.api.nvim_create_autocmd('Filetype', { pattern = "go,lua,vim,html,css,javascript,typescript,sh", callback = function() vim.opt.shiftwidth = 2; vim.opt.expandtab = true end, }) -- bernie: match extra named filenames vim.api.nvim_create_autocmd({'BufNewFile', 'BufRead'}, { pattern = "named.conf.*,named-*.conf", command = "setf named", }) -- Set this to replace GitHub default URLs local github_url = 'https://github.com/' -- local github_url = 'git@github.com:' -- Lazy local lazy_plugins = { { 'nvim-telescope/telescope.nvim', dependencies = { 'nvim-lua/plenary.nvim' } }, { 'nvim-telescope/telescope-symbols.nvim' }, { 'nvim-telescope/telescope-frecency.nvim' }, { 'nvim-tree/nvim-tree.lua', dependencies = { 'nvim-tree/nvim-web-devicons' }, version = '*' }, { 'nvim-treesitter/nvim-treesitter', build = ":TSUpdate", }, 'JamshedVesuna/vim-markdown-preview', 'mattkretz/vim-gnuindent', -- Code completion 'neovim/nvim-lspconfig', 'hrsh7th/cmp-nvim-lsp', 'hrsh7th/cmp-buffer', 'hrsh7th/cmp-path', 'hrsh7th/cmp-cmdline', 'hrsh7th/nvim-cmp', -- 'hrsh7th/cmp-nvim-lsp-signature-help', { 'ray-x/lsp_signature.nvim', lazy = true }, { "tzachar/cmp-ai", dependencies = "nvim-lua/plenary.nvim" }, { "folke/lazydev.nvim", ft = "lua", opts = { library = { -- Load luvit types when the `vim.uv` word is found { path = "luvit-meta/library", words={ "vim%.uv" } }, }, }, }, { "Bilal2453/luvit-meta", lazy = true }, -- Coding { "mrcjkb/rustaceanvim", lazy = false, }, { "olimorris/codecompanion.nvim", dependencies = { "nvim-lua/plenary.nvim", "nvim-treesitter/nvim-treesitter", "nvim-telescope/telescope.nvim", { "stevearc/dressing.nvim", opts = {}, }, }, config = true }, { "github/copilot.vim" }, { "numToStr/Comment.nvim", lazy = false }, 'mfussenegger/nvim-dap', -- Debugger Adapter Protocol -- Version control 'airblade/vim-gitgutter', 'tpope/vim-fugitive', -- TODO: replace with https://github.com/TimUntersberger/neogit ? 'wsdjeg/vim-fetch', -- TODO: find lua replacement? 'haya14busa/vim-asterisk', { 'vladdoster/remember.nvim', opts = {} }, -- UI { 'akinsho/bufferline.nvim', dependencies = { 'nvim-tree/nvim-web-devicons' } }, { 'nvim-lualine/lualine.nvim', dependencies = { 'nvim-tree/nvim-web-devicons' } }, 'dstein64/nvim-scrollview', { 'folke/which-key.nvim', event = 'VeryLazy', init = function() vim.o.timeout = true vim.o.timeoutlen = 300 end, opts = {} }, -- Theming and eyecandy { "lukas-reineke/indent-blankline.nvim", main = "ibl", opts = { indent = { char = '│', }, scope = { char = '┃', enabled = true, show_start = false, }, }, }, { 'norcalli/nvim-colorizer.lua', opts = {'*'} }, -- { "max397574/colortils.nvim" }, { 'folke/tokyonight.nvim', lazy = false, priority = 1000, opts = {} }, 'projekt0n/github-nvim-theme', 'HiPhish/rainbow-delimiters.nvim', 'echasnovski/mini.nvim', -- for animate -- { 'karb94/neoscroll.nvim', config = function() require('neoscroll').setup {} end }, } -- bootstrap lazy local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" if not vim.uv.fs_stat(lazypath) then vim.fn.system({ "git", "clone", "--filter=blob:none", github_url .. "folke/lazy.nvim.git", "--branch=stable", -- latest stable release lazypath, }) end vim.opt.rtp:prepend(lazypath) local lazy_opts = { concurrency = 4, git = { url_format = github_url .. "%s.git" }, } -- Avoids the warning from Lazy on config reload if not vim.g.lazy_did_setup then require("lazy").setup(lazy_plugins, lazy_opts) end require('scrollview').setup({ signs_on_startup = { 'conflicts', 'search', 'quickfix', 'diagnostics', 'loclist' }, -- signs_on_startup = { 'all' }, }) if vim.g.neovide then -- smooth scroll done in GUI vim.opt.winblend = 20 vim.opt.pumblend = 20 vim.g.neovide_floating_blur_amount_x = 2.0 vim.g.neovide_floating_blur_amount_y = 2.0 vim.g.neovide_cursor_trail_size = 0.2 vim.g.neovide_scroll_animation_far_lines = 5 vim.g.neovide_remember_window_size = true vim.g.neovide_input_ime = true else local animate = require('mini.animate') animate.setup { cursor = { enable = true, timing = animate.gen_timing.cubic({ duration = 100, unit = 'total' }), }, scroll = { enable = false, -- too jerky timing = animate.gen_timing.cubic({ duration = 150, unit = 'total' }), }, resize = { enable = true, timing = animate.gen_timing.cubic({ duration = 150, unit = 'total' }), }, open = { enable = true, }, close = { enable = true, }, } end -- vim-markdown-preview vim.g.vim_markdown_preview_use_xdg_open = '1' vim.g.vim_markdown_preview_hotkey = '' vim.g.vim_markdown_preview_github = 1 -- nvim-treesitter -- if github_url ~= nil then -- Replace GitHub url for all treesitter plugins for _, config in pairs(require("nvim-treesitter.parsers").get_parser_configs()) do config.install_info.url = config.install_info.url:gsub("https://github.com/", github_url) end end require("nvim-treesitter.install").prefer_git = true ---@diagnostic disable-next-line: missing-fields require("nvim-treesitter.configs").setup({ ensure_installed = { "bash", "c", "cpp", "lua", "markdown", "python", "rust", "vim", "vimdoc", "query" }, sync_install = true, auto_install = false, -- Requires tree-sitter CLI highlight = { enable = true }, indent = { enable = true }, }) require("nvim-web-devicons").setup { color_icons = true, default = true, strict = true, } -- Telescope -- local opts = { noremap = true, silent = true } local map = vim.keymap.set require('telescope').setup({ extensions = { frecency = { show_unindexed = true, }, } }) require('telescope').load_extension "frecency" local builtin = require('telescope.builtin') map('n', '', builtin.git_files, opts) map('n', 'ff', builtin.find_files, opts) map('n', 'fg', builtin.live_grep, opts) map('n', 'fb', builtin.buffers, opts) map('n', 'fh', builtin.help_tags, opts) map('n', 'fs', builtin.symbols, opts) map('n', 'tt', builtin.builtin, opts) -- nvim-tree -- require("nvim-tree").setup({ view = { width = 30, }, renderer = { group_empty = true, }, filters = { dotfiles = true, }, }) map('n', 'o', ':NvimTreeFocus', opts) map('n', 'O', ':NvimTreeFindFile', opts) -- nvim-cmp -- local cmp_kinds = { Text = "", Method = "󰆧", Function = "󰊕", Constructor = "", Field = "󰇽", Variable = "󰂡", Class = "󰠱", Interface = "", Module = "", Property = "󰜢", Unit = "", Value = "󰎠", Enum = "", Keyword = "󰌋", Snippet = "", Color = "󰏘", File = "󰈙", Reference = "", Folder = "󰉋", EnumMember = "", Constant = "󰏿", Struct = "", Event = "", Operator = "󰆕", TypeParameter = "󰅲", } local cmp_sources = { cmp_ai = "✨", nvim_lsp = "🛠️", } local cmp = require('cmp') cmp.setup({ formatting = { expandable_indicator = true, fields = { "kind", "abbr", "menu" }, format = function(entry, item) item.kind = cmp_kinds[item.kind] or "" item.menu = cmp_sources[entry.source.name] or entry.source.name local max_width = 50 if item.abbr ~= nil and string.len(item.abbr) > max_width then item.abbr = string.sub(item.abbr, 1, max_width - 1) .. "…" end return item end, }, mapping = cmp.mapping.preset.insert({ [''] = cmp.mapping(cmp.mapping.scroll_docs(-4), { 'i', 'c' }), [''] = cmp.mapping(cmp.mapping.scroll_docs(4), { 'i', 'c' }), [''] = cmp.mapping(cmp.mapping.complete(), { 'i', 'c' }), [''] = cmp.mapping({ i = cmp.mapping.abort(), c = cmp.mapping.close(), }), [''] = cmp.mapping.confirm({ select = true }), [''] = cmp.mapping.confirm({ select = true }), [''] = cmp.mapping.complete({ config = { sources = cmp.config.sources({ { name = 'cmp_ai' }, }), }, }), }), -- experimental = { ghost_text = true, }, sources = cmp.config.sources({ { name = "lazydev", group_index = 0, }, -- { name = "cmp_ai" }, { name = "nvim_lsp" }, }) }) cmp.setup.cmdline(':', { mapping = cmp.mapping.preset.cmdline(), completion = { keyword_length = 2, }, sources = cmp.config.sources({ { name = 'path', option = { trailing_slash = true, }, }, }, { { name = 'cmdline' } }), }) -- nvim-dap: Debugger config for C / C++ / Rust -- local dap = require('dap') dap.adapters.lldb = { type = 'executable', command = '/usr/bin/lldb-vscode', name = 'lldb' } dap.configurations.cpp = { { name = 'Launch', type = 'lldb', request = 'launch', program = function() return vim.fn.input('Path to executable: ', vim.fn.getcwd() .. '/', 'file') end, cwd = '${workspaceFolder}', stopOnEntry = true, args = {}, -- runInTerminal = false, }, } dap.configurations.c = dap.configurations.cpp dap.configurations.rust = dap.configurations.cpp dap.adapters.python = { type = 'executable', command = '/usr/bin/python', args = { '-m', 'debugpy.adapter' }, } dap.configurations.python = { { type = 'python', request = 'launch', name = "Launch file", program = "${file}", pythonPath = function() return '/usr/bin/python' end, }, } vim.diagnostic.config({ virtual_text = false, underline = true, update_in_insert = false, severity_sort = true, signs = { text = { [vim.diagnostic.severity.ERROR] = "", [vim.diagnostic.severity.WARN] = "", [vim.diagnostic.severity.INFO] = "", [vim.diagnostic.severity.HINT] = "?", }, }, float = { style = 'minimal', focusable = false, source = "if_many", header = '', prefix = '', } }) -- TODO: deprecated, convert to vim.diagnostic.config() vim.fn.sign_define('DapBreakpoint', { text = '🛑', texthl = '', linehl = '', numhl = '' }) -- LSP -- local on_lsp_attach = function(args) local client = vim.lsp.get_client_by_id(args.data.client_id) local bufnr = args.buf local opts = { noremap = true, silent = false, buffer = bufnr } if client and vim.tbl_contains({ "GitHub Copilot" }, client.name) then return -- blacklist LSP end -- require("lsp_signature").on_attach({ hi_parameter = "IncSearch" }, bufnr) -- Parse .vscode/launch.json and addconfigs require("dap.ext.vscode").load_launchjs(nil, { cppdbg = { "c", "cpp" } }) map('n', '', vim.lsp.buf.definition, opts) map('n', 'gd', vim.lsp.buf.definition, opts) map('n', 'gD', vim.lsp.buf.declaration, opts) map('n', 'gi', vim.lsp.buf.implementation, opts) map('n', 'gr', vim.lsp.buf.references, opts) map('n', 'K', vim.lsp.buf.hover, opts) map('n', '', vim.lsp.buf.signature_help, opts) map('n', 'D', vim.lsp.buf.type_definition, opts) map('n', 'gh', 'ClangdSwitchSourceHeader', opts) map('n', '', 'ClangdSwitchSourceHeader', opts) map('n', 'e', vim.diagnostic.open_float, opts) map('n', 'q', 'Telescope diagnostics', opts) map('n', 'wa', vim.lsp.buf.add_workspace_folder, opts) map('n', 'wr', vim.lsp.buf.remove_workspace_folder, opts) map('n', 'wl', function() print(vim.inspect(vim.lsp.buf.list_workspace_folders())) end, opts) map('n', 'rn', vim.lsp.buf.rename, opts) map('n', 'a', vim.lsp.buf.code_action, opts) map('n', 'h', function() vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled({})) end, opts) map({ 'n', 'v' }, '=', vim.lsp.buf.format, opts) map({ 'n', 'v' }, 'gq', vim.lsp.buf.format, opts) -- Mappings for inline debugging map('n', '', dap.continue, opts) map('n', '', dap.terminate, opts) map('n', '', dap.restart, opts) map('n', '', dap.toggle_breakpoint, opts) map('n', '', dap.step_over, opts) map('n', '', dap.step_into, opts) map('n', '', dap.step_out, opts) map('n', 'b', dap.toggle_breakpoint, opts) map('n', 'B', function() dap.set_breakpoint(vim.fn.input('Breakpoint condition: ')) end, opts) map('n', 'lp', function() dap.set_breakpoint(nil, nil, vim.fn.input('Log point message: ')) end, opts) map('n', 'dr', dap.repl.toggle, opts) map('n', 'dl', dap.run_last, opts) map({"n", "v"}, "dp", function() require("dap.ui.widgets").preview() end, opts) map("n", "df", function() local widgets = require("dap.ui.widgets") widgets.centered_float(widgets.frames) end, opts) map("n", "ds", function() local widgets = require("dap.ui.widgets") widgets.centered_float(widgets.scopes) end, opts) vim.api.nvim_create_autocmd("CursorHold", { buffer = bufnr, callback = function() vim.diagnostic.open_float(nil, { focus = false, severity = vim.diagnostic.severity.WARN }) end, }) if client and client.server_capabilities.documentHighlightProvider then vim.api.nvim_create_autocmd("CursorHold", { buffer = bufnr, callback = vim.lsp.buf.document_highlight }) vim.api.nvim_create_autocmd("CursorHoldI", { buffer = bufnr, callback = vim.lsp.buf.document_highlight }) vim.api.nvim_create_autocmd("CursorMoved", { buffer = bufnr, callback = vim.lsp.buf.clear_references }) end end -- vim.lsp.set_log_level("debug") vim.api.nvim_create_autocmd('LspAttach', { group = vim.api.nvim_create_augroup('UserLspConfig', {}), callback = on_lsp_attach, }) -- local capabilities = require('cmp_nvim_lsp').default_capabilities() local lspconfig = require("lspconfig") lspconfig.tsserver.setup({}) lspconfig.clangd.setup ({ cmd = { "clangd", "--background-index" }, root_dir = lspconfig.util.root_pattern("compile_commands.json", "compile_flags.txt"), }) lspconfig.pyright.setup({}) lspconfig.ruff_lsp.setup({}) lspconfig.lua_ls.setup ({ root_dir = lspconfig.util.root_pattern("init.lua", ".luarc.json", ".luarc.jsonc", ".luacheckrc", ".stylua.toml", "stylua.toml", "selene.toml", "selene.yml", ".git"), }) -- Bernie's historic mappings map({ 'n', 'c', 't', 'i' }, '', '') -- Disable F1 for help map('n', 'Q', '', opts) -- ex mode is useless and annoying map('n', '.', '.`[', opts) -- Repeat last command and put cursor at start of change map('n', ';', ':', opts) -- what's ; for anyway? map('c', 'w!!', 'w !sudo tee % >/dev/null', opts) -- :w!! if you forget to sudo before editing -- Comment.nvim mappings -- NOTE: means map('n', '', '(comment_toggle_linewise_current)') map('n', '', '(comment_toggle_blockwise_current)') map('x', '', '(comment_toggle_linewise_visual)') map('x', '', '(comment_toggle_blockwise_visual)') -- fix broken Page Up/Down -- http://vimrc-dissection.blogspot.com/2009/02/fixing-pageup-and-pagedown.html map({ 'n', 'i' }, '', '1000', opts) map({ 'n', 'i' }, '', '1000', opts) -- vim-asterisk vim.g['asterisk#keeppos'] = '1' map('n', '*', '(asterisk-*)') map('n', '#', '(asterisk-#)') map('n', 'g*', '(asterisk-g*)') map('n', 'g#', '(asterisk-g#)') map('n', 'z*', '(asterisk-z*)') map('n', 'gz*', '(asterisk-gz*)') map('n', 'z#', '(asterisk-z#)') map('n', 'gz#', '(asterisk-gz#)') -- Move between splits with ALT-cursors in normal, insert and terminal modes map({ 'n', 'i', 't' }, '', 'h', opts) map({ 'n', 'i', 't' }, '', 'j', opts) map({ 'n', 'i', 't' }, '', 'k', opts) map({ 'n', 'i', 't' }, '', 'l', opts) map({ 'n', 'i', 't' }, '', 'h', opts) map({ 'n', 'i', 't' }, '', 'j', opts) map({ 'n', 'i', 't' }, '', 'k', opts) map({ 'n', 'i', 't' }, '', 'l', opts) -- map({'i', 'n', 't'}, '', '', opts) -- Toggle line wrap with ALT-w map({ 'n', 'c', 't', 'i' }, '', function() vim.o.wrap = (vim.o.wrap == false); print('wrap', vim.o.wrap) end, opts) -- Terminal map('t', '', '', opts) -- Tweak the default PopUp menu vim.cmd [[ amenu PopUp.-1- amenu PopUp.How-to\ disable\ mouse aunmenu PopUp.-1- aunmenu PopUp.How-to\ disable\ mouse ]] require("tokyonight").setup({ style = "night", -- The theme comes in three styles, `storm`, `moon`, a darker variant `night` and `day` light_style = "day", -- The theme is used when the background is set to light transparent = false, -- Enable this to disable setting the background color terminal_colors = true, -- Configure the colors used when opening a `:terminal` in [Neovim](https://github.com/neovim/neovim) styles = { -- Style to be applied to different syntax groups -- Value is any valid attr-list value for `:help nvim_set_hl` comments = { italic = true }, keywords = { italic = false }, functions = {}, variables = {}, -- Background styles. Can be "dark", "transparent" or "normal" sidebars = "dark", -- style for sidebars, see below floats = "dark", -- style for floating windows }, sidebars = { "qf", "help" }, -- Set a darker background on sidebar-like windows. For example: `["qf", "vista_kind", "terminal", "packer"]` day_brightness = 0.3, -- Adjusts the brightness of the colors of the **Day** style. Number between 0 and 1, from dull to vibrant colors hide_inactive_statusline = false, -- Enabling this option, will hide inactive statuslines and replace them with a thin border instead. Should work with the standard **StatusLine** and **LuaLine**. dim_inactive = false, -- dims inactive windows lualine_bold = false, -- When `true`, section headers in the lualine theme will be bold --- You can override specific color groups to use other groups or a hex color --- function will be called with a ColorScheme table ---@param colors ColorScheme on_colors = function(colors) colors.bg = "#000814" -- Bluish background colors.fg = "#d0daf5" colors.comment = "#889988" end, --- You can override specific highlights to use other groups or a hex color --- function will be called with a Highlights and ColorScheme table ---@param hl Highlights ---@param _colors ColorScheme on_highlights = function(hl, _colors) local util = require("tokyonight.util") hl.CursorLine = { bg = "#001122" } hl.IblIndent = { fg = "#002233" } hl.IblScope = { fg = "#002255" } hl.LspReferenceRead = { bg = '#113311' } hl.LspReferenceWrite = { bg = '#331111' } hl.LspReferenceText = { } hl.MatchParen = { fg = '#000000', bg = '#bbbb44' } hl["@variable"] = { fg = util.lighten(hl["@variable"].fg, 0.7) } hl["@variable.parameter"] = { fg = util.lighten(hl["@variable.parameter"].fg, 0.7) } hl["@variable.member"] = { fg = util.lighten(hl["@variable.member"].fg, 0.7) } end, }) vim.cmd('colorscheme tokyonight') _ = {{{{{{{}}}}}}} -- Testing rainbow-delimiters require('bufferline').setup { options = { hover = { enabled = true, delay = 200, reveal = {'close'} } } } require('lualine').setup { options = { theme = 'codedark', -- theme = 'tokyonight', section_separators = { left = '', right = '' }, component_separators = { left = '', right = '' }, -- section_separators = '', component_separators = '', show_filename_only = false, globalstatus = false, }, sections = { lualine_a = { { 'mode', fmt = function(str) return str:sub(1, 1) end } }, lualine_b = { { 'branch', fmt = function(branch) return branch == 'master' and '' or branch end }, }, lualine_c = { { 'filename', path = 1, }, }, lualine_x = { { 'filetype', icon_only = true, }, }, lualine_y = {}, }, } --[[ local cmp_ai = require('cmp_ai.config') cmp_ai:setup({ max_lines = 1000, provider = 'Ollama', provider_options = { model = 'codestral', }, notify = true, run_on_every_keystroke = true, ignored_file_types = {}, }) --]] require("codecompanion").setup({ adapters = { openai = require("codecompanion.adapters").use("openai", { env = { api_key = "OPENAI_API_KEY", }, }), ollama = require("codecompanion.adapters").use("ollama", { schema = { model = { default = "codestral" }, }, }), }, strategies = { chat = "ollama", inline = "ollama", tool = "ollama" }, log_level = "DEBUG", })