chore(nvim): reinitialize with working config
Some checks are pending
Check Lua Formatting in MyRepo / Stylua Check (push) Waiting to run

This commit is contained in:
Jeremie Fraeys 2026-02-07 21:06:45 -05:00
commit 02e26b00b7
No known key found for this signature in database
98 changed files with 5274 additions and 0 deletions

28
.github/ISSUE_TEMPLATE/bug_report.md vendored Executable file
View file

@ -0,0 +1,28 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
<!-- Any bug report not following this template will be immediately closed. Thanks -->
## Describe the bug
<!-- A clear and concise description of what the bug is. -->
## To Reproduce
<!-- Steps to reproduce the behavior. -->
1. ...
## Desktop
<!-- please complete the following information. -->
- OS:
- Terminal:
## Neovim Version
<!-- Output of running `:version` from inside of neovim. -->
```
```

30
.github/workflows/stylua.yaml vendored Normal file
View file

@ -0,0 +1,30 @@
---
# Check Lua Formatting
name: Check Lua Formatting in MyRepo
on:
pull_request_target:
branches:
- main
push:
branches:
- main
jobs:
stylua-check:
name: Stylua Check
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
steps:
- name: Checkout Code
uses: actions/checkout@v2
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Stylua Check
uses: JohnnyMorganz/stylua-action@v3
with:
token: ${{ secrets.GITHUB_TOKEN }}
version: latest
args: --check .

7
.gitignore vendored Executable file
View file

@ -0,0 +1,7 @@
tags
test.sh
.luarc.json
nvim
lazy-lock.json
.DS_Store

8
.idea/.gitignore vendored Normal file
View file

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View file

@ -0,0 +1,13 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="PyUnresolvedReferencesInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ignoredIdentifiers">
<list>
<option value="dict.database" />
<option value="search_engine" />
</list>
</option>
</inspection_tool>
</profile>
</component>

View file

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

7
.idea/misc.xml Normal file
View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="Python 3.11" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11" project-jdk-type="Python SDK" />
</project>

6
.idea/vcs.xml Normal file
View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

10
.stylua.toml Executable file
View file

@ -0,0 +1,10 @@
column_width = 120
line_endings = "Unix"
indent_type = "Spaces"
indent_width = 2
call_parentheses = "Always"
quote_style = "AutoPreferSingle"
collapse_simple_statement = "Never"
[sort_requires]
enabled = false

19
LICENSE.md Executable file
View file

@ -0,0 +1,19 @@
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

159
README.md Executable file
View file

@ -0,0 +1,159 @@
# kickstart.nvim
https://github.com/kdheepak/kickstart.nvim/assets/1813121/f3ff9a2b-c31f-44df-a4fa-8a0d7b17cf7b
### Introduction
A starting point for Neovim that is:
* Small
* Single-file (with examples of moving to multi-file)
* Documented
* Modular
This repo is meant to be used by **YOU** to begin your Neovim journey; remove the things you don't use and add what you miss.
Kickstart.nvim targets *only* the latest ['stable'](https://github.com/neovim/neovim/releases/tag/stable) and latest ['nightly'](https://github.com/neovim/neovim/releases/tag/nightly) of Neovim. If you are experiencing issues, please make sure you have the latest versions.
Distribution Alternatives:
- [LazyVim](https://www.lazyvim.org/): A delightful distribution maintained by @folke (the author of lazy.nvim, the package manager used here)
### Installation
> **NOTE**
> [Backup](#FAQ) your previous configuration (if any exists)
Requirements:
* Make sure to review the readmes of the plugins if you are experiencing errors. In particular:
* [ripgrep](https://github.com/BurntSushi/ripgrep#installation) is required for multiple [telescope](https://github.com/nvim-telescope/telescope.nvim#suggested-dependencies) pickers.
* See [Windows Installation](#Windows-Installation) if you have trouble with `telescope-fzf-native`
Neovim's configurations are located under the following paths, depending on your OS:
| OS | PATH |
| :- | :--- |
| Linux | `$XDG_CONFIG_HOME/nvim`, `~/.config/nvim` |
| MacOS | `$XDG_CONFIG_HOME/nvim`, '~/.config/nvim` |
| Windows | `%userprofile%\AppData\Local\nvim\` |
Clone kickstart.nvim:
```sh
# on Linux and Mac
git clone https://github.com/nvim-lua/kickstart.nvim.git "${XDG_CONFIG_HOME:-$HOME/.config}"/nvim
# on Windows
git clone https://github.com/nvim-lua/kickstart.nvim.git %userprofile%\AppData\Local\nvim\
```
### Post Installation
Run the following command and then **you are ready to go**!
```sh
nvim --headless "+Lazy! sync" +qa
```
### Recommended Steps
[Fork](https://docs.github.com/en/get-started/quickstart/fork-a-repo) this repo (so that you have your own copy that you can modify) and then installing you can install to your machine using the methods above.
> **NOTE**
> Your fork's url will be something like this: `https://github.com/<your_github_username>/kickstart.nvim.git`
### Configuration And Extension
* Inside of your copy, feel free to modify any file you like! It's your copy!
* Feel free to change any of the default options in `init.lua` to better suit your needs.
* For adding plugins, there are 3 primary options:
* Add new configuration in `lua/custom/plugins/*` files, which will be auto sourced using `lazy.nvim` (uncomment the line importing the `custom/plugins` directory in the `init.lua` file to enable this)
* Modify `init.lua` with additional plugins.
* Include the `lua/kickstart/plugins/*` files in your configuration.
You can also merge updates/changes from the repo back into your fork, to keep up-to-date with any changes for the default configuration.
#### Example: Adding an autopairs plugin
In the file: `lua/custom/plugins/autopairs.lua`, add:
```lua
-- File: lua/custom/plugins/autopairs.lua
return {
"windwp/nvim-autopairs",
-- Optional dependency
dependencies = { 'hrsh7th/nvim-cmp' },
config = function()
require("nvim-autopairs").setup {}
-- If you want to automatically add `(` after selecting a function or method
local cmp_autopairs = require('nvim-autopairs.completion.cmp')
local cmp = require('cmp')
cmp.event:on(
'confirm_done',
cmp_autopairs.on_confirm_done()
)
end,
}
```
This will automatically install [windwp/nvim-autopairs](https://github.com/windwp/nvim-autopairs) and enable it on startup. For more information, see documentation for [lazy.nvim](https://github.com/folke/lazy.nvim).
#### Example: Adding a file tree plugin
In the file: `lua/custom/plugins/filetree.lua`, add:
```lua
-- Unless you are still migrating, remove the deprecated commands from v1.x
vim.cmd([[ let g:neo_tree_remove_legacy_commands = 1 ]])
return {
"nvim-neo-tree/neo-tree.nvim",
version = "*",
dependencies = {
"nvim-lua/plenary.nvim",
"nvim-tree/nvim-web-devicons", -- not strictly required, but recommended
"MunifTanjim/nui.nvim",
},
config = function ()
require('neo-tree').setup {}
end,
}
```
This will install the tree plugin and add the command `:Neotree` for you. You can explore the documentation at [neo-tree.nvim](https://github.com/nvim-neo-tree/neo-tree.nvim) for more information.
### Contribution
Pull-requests are welcome. The goal of this repo is not to create a Neovim configuration framework, but to offer a starting template that shows, by example, available features in Neovim. Some things that will not be included:
* Custom language server configuration (null-ls templates)
* Theming beyond a default colorscheme necessary for LSP highlight groups
Each PR, especially those which increase the line count, should have a description as to why the PR is necessary.
### FAQ
* What should I do if I already have a pre-existing neovim configuration?
* You should back it up, then delete all files associated with it.
* This includes your existing init.lua and the neovim files in `~/.local` which can be deleted with `rm -rf ~/.local/share/nvim/`
* You may also want to look at the [migration guide for lazy.nvim](https://github.com/folke/lazy.nvim#-migration-guide)
* What if I want to "uninstall" this configuration:
* See [lazy.nvim uninstall](https://github.com/folke/lazy.nvim#-uninstalling) information
* Are there any cool videos about this plugin?
* Current iteration of kickstart (coming soon)
* Here is one about the previous iteration of kickstart: [video introduction to Kickstart.nvim](https://youtu.be/stqUbv-5u2s). Note the install via init.lua no longer works as specified. Please follow the install instructions in this file instead as they're up to date.
### Windows Installation
Installation may require installing build tools, and updating the run command for `telescope-fzf-native`
See `telescope-fzf-native` documentation for [more details](https://github.com/nvim-telescope/telescope-fzf-native.nvim#installation)
This requires:
- Install CMake, and the Microsoft C++ Build Tools on Windows
```lua
{'nvim-telescope/telescope-fzf-native.nvim', build = 'cmake -S. -Bbuild -DCMAKE_BUILD_TYPE=Release && cmake --build build --config Release && cmake --install build --prefix build' }
```

View file

@ -0,0 +1,66 @@
;; Custom highlights for Go
;; Place this in: ~/.config/nvim/after/queries/go/highlights.scm
;; Highlight struct field names
(field_declaration
name: (field_identifier) @struct.field)
;; Highlight function receivers in method declarations
(parameter_declaration
name: (identifier) @function.receiver
type: (pointer_type (type_identifier))) ;; Pointer receivers
(parameter_declaration
name: (identifier) @function.receiver
type: (type_identifier)) ;; Value receivers
;; Highlight type parameters (Go 1.18+ Generics)
; (type_parameter
; name: (type_identifier) @type.parameter)
;; Better highlight for method calls
(selector_expression
field: (field_identifier) @method.call)
;; Improved context highlighting for function parameters
(function_declaration
name: (identifier) @function.name
parameters: (parameter_list
(parameter_declaration
name: (identifier) @function.parameter)))
;; Interface method names (fixed issue with invalid method_spec)
; (interface_type
; (field
; name: (field_identifier) @interface.method)) ;; Interface methods
;; Highlight builtin functions
((identifier) @function.builtin
(#any-of? @function.builtin "append" "cap" "close" "complex" "copy" "delete"
"imag" "len" "make" "new" "panic" "print" "println"
"real" "recover"))
;; Constants in ALL_CAPS (common Go convention)
((identifier) @constant
(#match? @constant "^[A-Z][A-Z0-9_]+$"))
;; Error variables (by Go convention, starting with "Err")
((identifier) @variable.error
(#match? @variable.error "^Err[A-Z]\\w*"))
;; Type declaration highlighting
(type_spec
name: (type_identifier) @type.definition)
;; Enhance composite literal highlighting
(composite_literal
type: (_) @composite.type)
;; Go build tags
(comment) @preproc.build
(#match? @preproc.build "^//go:build")
;; Go generate directives
(comment) @preproc.generate
(#match? @preproc.generate "^//go:generate")

View file

@ -0,0 +1,99 @@
;; extends
; Custom text objects for Go
; Place this in: ~/.config/nvim/after/queries/go/textobjects.scm
; Function text objects
(function_declaration) @function.outer
(function_declaration
body: (block) @function.inner)
; Method text objects
(method_declaration) @function.outer
(method_declaration
body: (block) @function.inner)
; Function literal (closure) text objects
(func_literal) @function.outer
(func_literal
body: (block) @function.inner)
; Class text objects (structs, interfaces)
(type_declaration) @class.outer
; (struct_type
; "{" "}" @class.inner)
(interface_type
"{" "}" @class.inner)
; Parameter text objects
(parameter_list) @parameter.outer
(parameter_list
"(" . (_) @_start (_)? @_end . ")"
(#make-range! "parameter.inner" @_start @_end))
; Argument text objects
(argument_list) @parameter.outer
(argument_list
"(" . (_) @_start (_)? @_end . ")"
(#make-range! "parameter.inner" @_start @_end))
; Comment text objects
(comment) @comment.outer
; Block text objects
(block) @block.outer
(block
"{" . (_) @_start (_)? @_end . "}"
(#make-range! "block.inner" @_start @_end))
; Statement text objects
; (simple_statement) @statement.outer
(expression_statement) @statement.outer
(if_statement) @statement.outer
(for_statement) @statement.outer
; (switch_statement) @statement.outer
(select_statement) @statement.outer
(return_statement) @statement.outer
(defer_statement) @statement.outer
(go_statement) @statement.outer
; Conditional text objects
(if_statement) @conditional.outer
; (if_statement
; body: (block) @conditional.inner)
; Loop text objects
(for_statement) @loop.outer
(for_statement
body: (block) @loop.inner)
; Call text objects
(call_expression) @call.outer
(call_expression
arguments: (argument_list) @call.inner)
; Assignment text objects
(assignment_statement) @assignment.outer
(short_var_declaration) @assignment.outer
; Import text objects
(import_declaration) @import.outer
(import_spec_list) @import.inner
; Package text objects
(package_clause) @package.outer
; Attribute/field text objects
(field_declaration) @attribute.outer

View file

@ -0,0 +1,15 @@
; (atx_heading
; heading_content: (_) @class.inner) @class.outer
;
; (setext_heading
; heading_content: (_) @class.inner) @class.outer
;
; (thematic_break) @class.outer
(fenced_code_block (code_fence_content) @block.inner) @block.outer
[
(paragraph)
(list)
] @block.outer

View file

@ -0,0 +1,13 @@
;extends
[
(shortcut_link)
] @nospell
(strikethrough
(emphasis_delimiter)
(strikethrough
(emphasis_delimiter)
(emphasis_delimiter))
(emphasis_delimiter))@markup.doublestrikethrough

View file

@ -0,0 +1,12 @@
; Injection for code blocks
(ranged_verbatim_tag (tag_name) @_tagname (tag_parameters .(tag_param) @injection.language) (ranged_verbatim_tag_content) @injection.content (#any-of? @_tagname "code" "embed"))
(ranged_verbatim_tag (tag_name) @_tagname (tag_parameters)? (ranged_verbatim_tag_content) @injection.content (#eq? @_tagname "math") (#set! injection.language "latex"))
(
(inline_math) @injection.content
(#offset! @injection.content 0 1 0 -1)
(#set! injection.language "latex")
)
(ranged_verbatim_tag (tag_name) @_tagname (ranged_verbatim_tag_content) @injection.content (#eq? @_tagname "document.meta") (#set! injection.language "norg_meta"))

View file

@ -0,0 +1,12 @@
;extends
(
(comment) @comment
(#match? @comment "^\\#\\|")
) @text.literal
(
(comment) @content
(#match? @content "^\\# ?\\%\\%")
) @class.outer @text.literal

View file

@ -0,0 +1,7 @@
;extends
(
(comment) @content1
(#match? @content1 "^\\# ?\\%\\%")
) @class.inner

View file

@ -0,0 +1,50 @@
; block
; call
(call) @call.outer
(arguments) @call.inner
; class
; comment
(comment) @comment.outer
; conditional
(if_statement
condition: (_)? @conditional.inner) @conditional.outer
; function
[
(function_definition)
] @function.outer
(function_definition
[
(call)
(binary_operator)
] @function.inner) @function.outer
; loop
[
(while_statement)
(for_statement)
(repeat_statement)
] @loop.outer
(while_statement
body: (_) @loop.inner)
(repeat_statement
body: (_) @loop.inner)
(for_statement
body: (_) @loop.inner)
; statement
(program
(_) @statement.outer)
; number
(float) @number.inner

View file

@ -0,0 +1,15 @@
;extends
(macro_invocation
(scoped_identifier
path: (identifier) @path (#eq? @path "sqlx")
name: (identifier) @name (#match? @name "^query.*")
)
(token_tree
(raw_string_literal) @injection.content
(#set! injection.language "sql")
(#set! injection.include-children)
)
(#offset! @injection.content 0 3 0 -2)
)

196
ftplugin/c.lua Normal file
View file

@ -0,0 +1,196 @@
-- Indentation settings
vim.bo.expandtab = true -- Use spaces instead of tabs
vim.bo.tabstop = 4 -- Number of spaces per tab
vim.bo.shiftwidth = 4 -- Number of spaces for autoindent
vim.bo.softtabstop = 4 -- Number of spaces for editing
vim.bo.formatoptions = vim.bo.formatoptions:gsub('o', '') -- Remove 'o'
-- Format on save using Conform
local augroup = vim.api.nvim_create_augroup('CFormat', { clear = true })
vim.api.nvim_create_autocmd('BufWritePre', {
group = augroup,
pattern = '*.c',
callback = function()
if vim.fn.exists(':ConformFormat') == 2 then
vim.cmd('ConformFormat')
end
end,
})
local function cmake_build_dir(name)
local dir = vim.fn.getcwd() .. '/' .. (name or 'build')
if vim.fn.isdirectory(dir) == 0 then
vim.fn.mkdir(dir, 'p')
end
return dir
end
local function cmake_configure(build_dir, extra_args)
local args = extra_args or ''
local bin_dir = vim.fn.getcwd() .. '/bin'
vim.fn.mkdir(bin_dir, 'p')
local out_args =
' -DCMAKE_RUNTIME_OUTPUT_DIRECTORY=' .. vim.fn.shellescape(bin_dir) .. ' -DCMAKE_LIBRARY_OUTPUT_DIRECTORY='
.. vim.fn.shellescape(bin_dir)
.. ' -DCMAKE_ARCHIVE_OUTPUT_DIRECTORY='
.. vim.fn.shellescape(bin_dir)
vim.cmd('!cmake -S . -B ' .. vim.fn.fnameescape(build_dir) .. out_args .. ' ' .. args)
end
local function cmake_build(build_dir)
vim.cmd('!cmake --build ' .. vim.fn.fnameescape(build_dir))
end
local function cmake_ctest(build_dir)
vim.cmd('!ctest --test-dir ' .. vim.fn.fnameescape(build_dir) .. ' --output-on-failure')
end
local function toggle_debugger_repl()
local dbg = vim.__c_dbg_term
if dbg and dbg.is_open and dbg:is_open() then
dbg:close()
return
end
local ok_term, term_mod = pcall(require, 'toggleterm.terminal')
if not ok_term then
return
end
local cmd
if vim.fn.has('mac') == 1 then
cmd = 'lldb'
else
cmd = 'gdb'
end
if not vim.__c_dbg_term then
vim.__c_dbg_term = term_mod.Terminal:new({
cmd = cmd,
direction = 'vertical',
size = function()
return math.floor(vim.o.columns * 0.4)
end,
hidden = true,
on_open = function(term)
vim.api.nvim_buf_set_keymap(term.bufnr, 'n', 'q', '<cmd>close<CR>', { noremap = true, silent = true })
vim.api.nvim_buf_set_keymap(term.bufnr, 't', '<Esc><Esc>', '<C-\\><C-n>', { noremap = true, silent = true })
end,
})
end
vim.__c_dbg_term:open()
vim.cmd('wincmd p')
end
local opts = { buffer = true, silent = true }
local function switch_source_header()
local bufnr = vim.api.nvim_get_current_buf()
local function edit_file(fname)
if not fname or fname == '' then
return
end
vim.cmd('edit ' .. vim.fn.fnameescape(fname))
end
local clangd
for _, client in ipairs(vim.lsp.get_clients({ bufnr = bufnr })) do
if client.name == 'clangd' then
clangd = client
break
end
end
if clangd then
clangd.request('textDocument/switchSourceHeader', { uri = vim.uri_from_bufnr(bufnr) }, function(err, result)
if err then
vim.notify('clangd: switchSourceHeader failed', vim.log.levels.WARN)
return
end
if not result then
vim.notify('No corresponding header/source found', vim.log.levels.INFO)
return
end
vim.schedule(function()
edit_file(vim.uri_to_fname(result))
end)
end, bufnr)
return
end
local file = vim.api.nvim_buf_get_name(bufnr)
if file == '' then
return
end
local root = file:gsub('%.[^%.]+$', '')
local ext = vim.fn.fnamemodify(file, ':e')
local candidates
if ext == 'h' or ext == 'hpp' or ext == 'hh' or ext == 'hxx' then
candidates = { 'c', 'cpp', 'cc', 'cxx' }
elseif ext == 'c' then
candidates = { 'h' }
else
candidates = { 'h', 'hpp', 'hh', 'hxx' }
end
for _, e in ipairs(candidates) do
local cand = root .. '.' .. e
if vim.fn.filereadable(cand) == 1 then
edit_file(cand)
return
end
end
vim.notify('No corresponding header/source found', vim.log.levels.INFO)
end
local function memory_profile_command(run_cmd)
if vim.fn.has('mac') == 1 then
return 'leaks --atExit -- ' .. run_cmd
end
return 'valgrind --leak-check=full --track-origins=yes ' .. run_cmd
end
vim.keymap.set('n', '<leader>cb', function()
local build_dir = cmake_build_dir('build')
cmake_configure(build_dir)
cmake_build(build_dir)
end, vim.tbl_extend('force', opts, { desc = 'CMake: Build' }))
vim.keymap.set('n', '<leader>ct', function()
local build_dir = cmake_build_dir('build')
cmake_ctest(build_dir)
end, vim.tbl_extend('force', opts, { desc = 'CMake: Test' }))
vim.keymap.set('n', '<leader>ch', switch_source_header, vim.tbl_extend('force', opts, { desc = 'C: Switch header/source' }))
vim.keymap.set('n', '<leader>cg', toggle_debugger_repl, vim.tbl_extend('force', opts, { desc = 'C: Toggle debugger REPL' }))
vim.keymap.set('n', '<leader>cm', function()
local cmd = vim.fn.input('Memory profile run: ', './bin/')
if cmd == '' then
return
end
vim.cmd('!' .. memory_profile_command(cmd))
end, vim.tbl_extend('force', opts, { desc = 'C: Memory profile (leaks/valgrind)' }))
vim.keymap.set('n', '<leader>Rr', toggle_debugger_repl, vim.tbl_extend('force', opts, { desc = 'Run/REPL: Toggle' }))
vim.keymap.set('n', '<leader>Rf', function()
local cmd = vim.fn.input('Run: ', './bin/')
if cmd == '' then
return
end
vim.cmd('!' .. cmd)
end, vim.tbl_extend('force', opts, { desc = 'Run/REPL: Run' }))
vim.keymap.set('n', '<leader>Ri', function()
local dbg = vim.__c_dbg_term
if dbg and dbg.send and dbg.is_open and dbg:is_open() then
dbg:send('\x03')
end
end, vim.tbl_extend('force', opts, { desc = 'Run/REPL: Interrupt' }))

256
ftplugin/cpp.lua Normal file
View file

@ -0,0 +1,256 @@
vim.opt_local.cinoptions = vim.opt_local.cinoptions + '0{1' -- Places opening brace on the same line as function signature
vim.opt_local.smartindent = true -- Automatically adds indentation where needed
vim.opt_local.tabstop = 4 -- Set tab stop to 4 spaces
vim.opt_local.shiftwidth = 4 -- Set shift width to 4 spaces
vim.opt_local.softtabstop = 4 -- Use spaces instead of tabs
vim.api.nvim_create_user_command('RunCpp', function(opts)
vim.cmd('w') -- Save the current file
local filename = vim.fn.expand('%') -- Get current file name
local output = 'bin/' .. vim.fn.expand('%:r'):match('([^/]+)$') .. '.out' -- Output file with .out extension
-- Use provided compiler or default to 'clang++'
local compiler = opts.args ~= '' and opts.args or 'clang++'
-- Ensure the output directory exists
vim.fn.mkdir('bin', 'p')
-- Compile and run the C++ code
vim.cmd('!' .. compiler .. ' ' .. filename .. ' -o ' .. output .. ' && ./' .. output)
end, { nargs = '?' }) -- Accepts one optional argument for the compiler
local function cmake_build_dir(name)
local dir = vim.fn.getcwd() .. '/' .. (name or 'build')
if vim.fn.isdirectory(dir) == 0 then
vim.fn.mkdir(dir, 'p')
end
return dir
end
local function cmake_configure(build_dir, extra_args)
local args = extra_args or ''
local bin_dir = vim.fn.getcwd() .. '/bin'
vim.fn.mkdir(bin_dir, 'p')
local out_args =
' -DCMAKE_RUNTIME_OUTPUT_DIRECTORY=' .. vim.fn.shellescape(bin_dir) .. ' -DCMAKE_LIBRARY_OUTPUT_DIRECTORY='
.. vim.fn.shellescape(bin_dir)
.. ' -DCMAKE_ARCHIVE_OUTPUT_DIRECTORY='
.. vim.fn.shellescape(bin_dir)
vim.cmd('!cmake -S . -B ' .. vim.fn.fnameescape(build_dir) .. out_args .. ' ' .. args)
end
local function cmake_build(build_dir, extra_args)
local args = extra_args or ''
vim.cmd('!cmake --build ' .. vim.fn.fnameescape(build_dir) .. ' ' .. args)
end
local function cmake_ctest(build_dir)
vim.cmd('!ctest --test-dir ' .. vim.fn.fnameescape(build_dir) .. ' --output-on-failure')
end
local function select_cmake_preset()
local lines = vim.fn.systemlist('cmake --list-presets')
local presets = {}
for _, line in ipairs(lines) do
local name = line:match('^%s*"([^"]+)"')
if name then
table.insert(presets, name)
end
end
if #presets == 0 then
return
end
vim.ui.select(presets, { prompt = 'CMake preset' }, function(choice)
if choice then
vim.g.cmake_preset = choice
end
end)
end
local function cmake_configure_with_preset()
local preset = vim.g.cmake_preset
if preset and preset ~= '' then
vim.cmd('!cmake --preset ' .. preset)
return true
end
return false
end
local function cmake_build_with_preset()
local preset = vim.g.cmake_preset
if preset and preset ~= '' then
vim.cmd('!cmake --build --preset ' .. preset)
return true
end
return false
end
local function toggle_debugger_repl()
local dbg = vim.__cpp_dbg_term
if dbg and dbg.is_open and dbg:is_open() then
dbg:close()
return
end
local ok_term, term_mod = pcall(require, 'toggleterm.terminal')
if not ok_term then
return
end
local cmd
if vim.fn.has('mac') == 1 then
cmd = 'lldb'
else
cmd = 'gdb'
end
if not vim.__cpp_dbg_term then
vim.__cpp_dbg_term = term_mod.Terminal:new({
cmd = cmd,
direction = 'vertical',
size = function()
return math.floor(vim.o.columns * 0.4)
end,
hidden = true,
on_open = function(term)
vim.api.nvim_buf_set_keymap(term.bufnr, 'n', 'q', '<cmd>close<CR>', { noremap = true, silent = true })
vim.api.nvim_buf_set_keymap(term.bufnr, 't', '<Esc><Esc>', '<C-\\><C-n>', { noremap = true, silent = true })
end,
})
end
vim.__cpp_dbg_term:open()
vim.cmd('wincmd p')
end
local opts = { buffer = true, silent = true }
local function switch_source_header()
local bufnr = vim.api.nvim_get_current_buf()
local function edit_file(fname)
if not fname or fname == '' then
return
end
vim.cmd('edit ' .. vim.fn.fnameescape(fname))
end
local clangd
for _, client in ipairs(vim.lsp.get_clients({ bufnr = bufnr })) do
if client.name == 'clangd' then
clangd = client
break
end
end
if clangd then
clangd.request('textDocument/switchSourceHeader', { uri = vim.uri_from_bufnr(bufnr) }, function(err, result)
if err then
vim.notify('clangd: switchSourceHeader failed', vim.log.levels.WARN)
return
end
if not result then
vim.notify('No corresponding header/source found', vim.log.levels.INFO)
return
end
vim.schedule(function()
edit_file(vim.uri_to_fname(result))
end)
end, bufnr)
return
end
local file = vim.api.nvim_buf_get_name(bufnr)
if file == '' then
return
end
local root = file:gsub('%.[^%.]+$', '')
local ext = vim.fn.fnamemodify(file, ':e')
local candidates
if ext == 'h' or ext == 'hpp' or ext == 'hh' or ext == 'hxx' then
candidates = { 'cpp', 'cc', 'cxx', 'c' }
elseif ext == 'c' then
candidates = { 'h' }
else
candidates = { 'h', 'hpp', 'hh', 'hxx' }
end
for _, e in ipairs(candidates) do
local cand = root .. '.' .. e
if vim.fn.filereadable(cand) == 1 then
edit_file(cand)
return
end
end
vim.notify('No corresponding header/source found', vim.log.levels.INFO)
end
local function memory_profile_command(run_cmd)
if vim.fn.has('mac') == 1 then
return 'leaks --atExit -- ' .. run_cmd
end
return 'valgrind --leak-check=full --track-origins=yes ' .. run_cmd
end
vim.keymap.set('n', '<leader>cS', select_cmake_preset, vim.tbl_extend('force', opts, { desc = 'CMake: Select preset' }))
vim.keymap.set('n', '<leader>cb', function()
if cmake_configure_with_preset() then
cmake_build_with_preset()
return
end
local build_dir = cmake_build_dir('build')
cmake_configure(build_dir)
cmake_build(build_dir)
end, vim.tbl_extend('force', opts, { desc = 'CMake: Build' }))
vim.keymap.set('n', '<leader>ct', function()
local build_dir = cmake_build_dir('build')
cmake_ctest(build_dir)
end, vim.tbl_extend('force', opts, { desc = 'CMake: Test' }))
vim.keymap.set('n', '<leader>cr', function()
local cmd = vim.fn.input('Run command: ', './')
if cmd == '' then
return
end
vim.cmd('!' .. cmd)
end, vim.tbl_extend('force', opts, { desc = 'CMake: Run (prompt)' }))
vim.keymap.set('n', '<leader>ch', switch_source_header, vim.tbl_extend('force', opts, { desc = 'C++: Switch header/source' }))
vim.keymap.set('n', '<leader>cg', toggle_debugger_repl, vim.tbl_extend('force', opts, { desc = 'C++: Toggle debugger REPL' }))
vim.keymap.set('n', '<leader>cm', function()
local cmd = vim.fn.input('Memory profile run: ', './bin/')
if cmd == '' then
return
end
vim.cmd('!' .. memory_profile_command(cmd))
end, vim.tbl_extend('force', opts, { desc = 'C++: Memory profile (leaks/valgrind)' }))
vim.keymap.set('n', '<leader>Rr', toggle_debugger_repl, vim.tbl_extend('force', opts, { desc = 'Run/REPL: Toggle' }))
vim.keymap.set('n', '<leader>Rf', function()
local cmd = vim.fn.input('Run: ', './bin/')
if cmd == '' then
return
end
vim.cmd('!' .. cmd)
end, vim.tbl_extend('force', opts, { desc = 'Run/REPL: Run' }))
vim.keymap.set('n', '<leader>Ri', function()
local dbg = vim.__cpp_dbg_term
if dbg and dbg.send and dbg.is_open and dbg:is_open() then
dbg:send('\x03')
end
end, vim.tbl_extend('force', opts, { desc = 'Run/REPL: Interrupt' }))
vim.keymap.set('n', '<leader>ca', function()
local build_dir = cmake_build_dir('build-asan')
local flags = "-DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_FLAGS='-fsanitize=address -fno-omit-frame-pointer' -DCMAKE_CXX_FLAGS='-fsanitize=address -fno-omit-frame-pointer'"
cmake_configure(build_dir, flags)
cmake_build(build_dir)
end, vim.tbl_extend('force', opts, { desc = 'CMake: Build (ASan)' }))

1
ftplugin/crontab.lua Normal file
View file

@ -0,0 +1 @@
vim.opt_local.fixeol = false

2
ftplugin/dockerfile.lua Normal file
View file

@ -0,0 +1,2 @@
vim.opt_local.expandtab = true
vim.opt_local.shiftwidth = 2

35
ftplugin/go.lua Normal file
View file

@ -0,0 +1,35 @@
-- Set buffer-local options for Go files
vim.bo.expandtab = true -- Use spaces instead of tabs
vim.opt_local.shiftwidth = 4 -- Indent width
vim.opt_local.tabstop = 4 -- Tab width
vim.opt_local.softtabstop = 4 -- Soft tab width for alignment
vim.bo.commentstring = '// %s' -- Comment format for Go
vim.opt_local.comments = 's1:/*,mb:*,ex:*/,://'
-- Define a buffer-local key mapping to trigger Go debugging
vim.keymap.set('n', '<leader>dd', function()
require('dap-go').debug_test()
end, { buffer = 0, desc = 'Debug Go Test' }) -- Buffer-local key mapping
-- Load nvim-dap-go and set up configurations
require('dap-go').setup()
-- Go DAP configuration
local dap = require('dap')
-- Define Go DAP configurations
dap.configurations.go = {
{
type = 'go',
name = 'Launch File',
request = 'launch',
program = '${file}',
},
{
type = 'go',
name = 'Launch Package',
request = 'launch',
program = '${workspaceFolder}',
},
}

16
ftplugin/json.lua Normal file
View file

@ -0,0 +1,16 @@
-- Use 2 spaces for indentation
vim.bo.shiftwidth = 2
vim.bo.tabstop = 2
vim.bo.expandtab = true
vim.bo.textwidth = 100
vim.wo.wrap = false
-- Enable spell-check for JSON comments
vim.wo.spell = true
-- Enable Folding for JSON
vim.wo.foldmethod = 'syntax'
-- Set conceal level for better JSON readability (e.g., hiding quotes)
vim.wo.conceallevel = 2

163
ftplugin/julia.lua Normal file
View file

@ -0,0 +1,163 @@
local ok_conform, conform = pcall(require, 'conform')
if ok_conform then
conform.formatters = conform.formatters or {}
conform.formatters_by_ft = conform.formatters_by_ft or {}
conform.formatters_by_ft.julia = { 'juliaformatter' }
vim.api.nvim_create_autocmd('BufWritePre', {
buffer = 0,
callback = function()
if vim.api.nvim_buf_line_count(0) > 2000 then
return
end
conform.format({ timeout_ms = 2000, lsp_fallback = false })
end,
})
end
if not vim.g.julia_repl_setup_done then
vim.g.julia_repl_setup_done = true
local ok_toggleterm, toggleterm_terminal = pcall(require, 'toggleterm.terminal')
if not ok_toggleterm then
return
end
local Terminal = toggleterm_terminal.Terminal
local function get_startup_commands()
return [[
ENV["JULIA_NOVERSIONS"] = "yes"
try
using Revise
catch
end
println("\033[2J\033[H")
]]
end
local function new_julia_terminal()
return Terminal:new({
cmd = 'julia --banner=no',
direction = 'vertical',
size = 80,
hidden = true,
on_open = function(term)
vim.defer_fn(function()
term:send(get_startup_commands())
end, 100)
vim.api.nvim_buf_set_keymap(term.bufnr, 'n', 'q', '<cmd>close<CR>', { noremap = true, silent = true })
vim.api.nvim_buf_set_keymap(term.bufnr, 't', '<Esc>', '<C-\\><C-n>', { noremap = true, silent = true })
local win = term.window or vim.api.nvim_get_current_win()
vim.api.nvim_set_option_value('signcolumn', 'no', { win = win })
vim.api.nvim_set_option_value('number', false, { win = win })
vim.api.nvim_set_option_value('relativenumber', false, { win = win })
end,
on_exit = function(_)
vim.cmd('stopinsert')
end,
})
end
vim.__julia_repl_terminal = new_julia_terminal()
vim.api.nvim_create_user_command('JuliaREPL', function()
local julia = vim.__julia_repl_terminal
if not julia then
vim.__julia_repl_terminal = new_julia_terminal()
julia = vim.__julia_repl_terminal
end
if julia:is_open() then
julia:close()
else
julia:open()
vim.cmd('wincmd p')
end
end, {})
vim.keymap.set('n', '<leader>Rr', '<cmd>JuliaREPL<CR>', { noremap = true, silent = true, desc = 'Run/REPL: Toggle' })
end
local function send_to_julia(code)
local julia = vim.__julia_repl_terminal
if not julia then
return
end
if not julia:is_open() then
julia:open()
vim.defer_fn(function()
julia:send(code)
vim.cmd('wincmd p')
end, 200)
else
julia:send(code)
vim.cmd('wincmd p')
end
end
local function get_cell_content()
local cur_line = vim.api.nvim_win_get_cursor(0)[1]
local lines = vim.api.nvim_buf_get_lines(0, 0, -1, false)
local start_line, end_line = cur_line, cur_line
while start_line > 1 and not lines[start_line - 1]:match('^#%%') and not lines[start_line - 1]:match('^##') do
start_line = start_line - 1
end
while end_line < #lines and not lines[end_line + 1]:match('^#%%') and not lines[end_line + 1]:match('^##') do
end_line = end_line + 1
end
return table.concat(vim.api.nvim_buf_get_lines(0, start_line - 1, end_line, false), '\n')
end
local opts = { buffer = true, silent = true }
vim.keymap.set('n', '<leader>Rf', function()
send_to_julia('using Revise\nincludet("' .. vim.fn.expand('%:p') .. '")\n')
end, vim.tbl_extend('force', opts, { desc = 'Run/REPL: Run file' }))
vim.keymap.set('n', '<leader>Rl', function()
send_to_julia(vim.api.nvim_get_current_line() .. '\n')
end, vim.tbl_extend('force', opts, { desc = 'Run/REPL: Send line' }))
vim.keymap.set('n', '<leader>Rc', function()
send_to_julia(get_cell_content() .. '\n')
end, vim.tbl_extend('force', opts, { desc = 'Run/REPL: Send cell' }))
vim.keymap.set('v', '<leader>Rs', function()
local start_pos = vim.fn.getpos("'<")[2]
local end_pos = vim.fn.getpos("'>")[2]
local code = table.concat(vim.api.nvim_buf_get_lines(0, start_pos - 1, end_pos, false), '\n')
send_to_julia(code .. '\n')
end, vim.tbl_extend('force', opts, { desc = 'Run/REPL: Send selection' }))
vim.keymap.set('n', '<leader>Ri', function()
send_to_julia('\x03')
end, vim.tbl_extend('force', opts, { desc = 'Run/REPL: Interrupt' }))
vim.keymap.set('n', '<leader>jb', function()
send_to_julia('using BenchmarkTools\n@btime ' .. vim.api.nvim_get_current_line() .. '\n')
end, vim.tbl_extend('force', opts, { desc = 'Julia: Benchmark line' }))
vim.keymap.set('n', '<leader>Rx', function()
local julia = vim.__julia_repl_terminal
if julia then
pcall(function()
julia:shutdown()
end)
end
vim.__julia_repl_terminal = Terminal:new({
cmd = 'julia --banner=no',
direction = 'vertical',
size = 80,
hidden = true,
})
end, vim.tbl_extend('force', opts, { desc = 'Run/REPL: Restart' }))
vim.g.julia_ftplugin_migrated = true

9
ftplugin/lua.lua Normal file
View file

@ -0,0 +1,9 @@
vim.opt.expandtab = true
vim.opt.shiftwidth = 2
vim.opt.tabstop = 2
vim.opt.softtabstop = 2
vim.opt_local.formatoptions:remove('o')
vim.opt_local.commentstring = '-- %s'
vim.opt_local.colorcolumn = '120'

24
ftplugin/make.lua Normal file
View file

@ -0,0 +1,24 @@
-- Use tabs for indentation (Makefiles require tabs in rules)
vim.bo.expandtab = false
vim.bo.shiftwidth = 4
vim.bo.tabstop = 4
vim.bo.softtabstop = 4
-- Show trailing spaces and tabs explicitly for visibility
vim.wo.list = true
vim.opt.listchars:append({ tab = '', trail = '·' })
-- Disable automatic comment continuation
vim.opt_local.formatoptions:remove('o')
-- Highlight spaces before tabs (helps detect incorrect indentation)
vim.cmd([[ match Error /^\s\+\t/ ]])
-- Enable line numbers for better navigation
vim.wo.number = true
-- Disable spell checking for Makefiles
vim.wo.spell = false
-- Set conceal level to 0 (Makefiles don't need concealment)
vim.wo.conceallevel = 0

101
ftplugin/markdown.lua Normal file
View file

@ -0,0 +1,101 @@
vim.opt_local.textwidth = 80
vim.opt_local.wrap = true
vim.opt_local.linebreak = true
-- Update PATH to include TeX binaries
vim.env.PATH = vim.env.PATH .. ':/Library/TeX/texbin'
local function ensure_directory_exists(path)
if not vim.fn.isdirectory(path) then
vim.fn.mkdir(path, 'p')
end
end
local function generate_pdf_paths(filename)
local base_dir = vim.fn.fnamemodify(filename, ':h')
local target_dir = base_dir:gsub('/src$', '/pdf')
local output_file = vim.fn.fnamemodify(filename, ':t:r') .. '.pdf'
local output_path = target_dir .. '/' .. output_file
ensure_directory_exists(target_dir)
return target_dir, output_file, output_path
end
local function build_pdf(filename, output_path)
local command = string.format('buildnote %s %s', vim.fn.shellescape(filename), vim.fn.shellescape(output_path))
return vim.fn.systemlist(command)
end
local function open_pdf_in_zathura(pdf_path)
local zathura_running = vim.fn.systemlist('pgrep -f "zathura ' .. vim.fn.shellescape(pdf_path) .. '"')
if #zathura_running == 0 then
vim.fn.jobstart({ 'zathura', pdf_path }, { detach = true, stdout = 'null', stderr = 'null' })
print('Opening PDF in Zathura: ' .. pdf_path)
else
print('Zathura is already running for this file.')
end
end
local function close_zathura()
local _, _, output_path = generate_pdf_paths(vim.fn.expand('%:p'))
vim.fn.system({ 'pkill', '-f', 'zathura ' .. output_path })
end
vim.keymap.set('n', '<leader>Rv', function()
local filename = vim.fn.expand('%:p')
local _, _, output_path = generate_pdf_paths(filename)
local result = build_pdf(filename, output_path)
if #result == 0 then
print('Error: Could not generate PDF.')
return
end
open_pdf_in_zathura(output_path)
end, {
desc = 'View output PDF in Zathura',
noremap = true,
silent = true,
})
vim.keymap.set('n', '<leader>Rc', close_zathura, {
desc = 'Close Zathura instance for the current PDF',
noremap = true,
silent = true,
})
vim.keymap.set('n', '<leader>Rb', function()
local filename = vim.fn.expand('%:p')
local _, _, output_path = generate_pdf_paths(filename)
local result = build_pdf(filename, output_path)
if #result == 0 then
print('Error: Could not generate PDF.')
return
end
print('PDF generated at: ' .. output_path)
end, {
desc = 'Build PDF',
noremap = true,
silent = true,
})
vim.api.nvim_create_autocmd('BufWritePost', {
pattern = '*note-*.md',
callback = function()
local filename = vim.fn.expand('%:p')
local _, _, output_path = generate_pdf_paths(filename)
if vim.fn.filereadable(filename) == 1 then
local command = string.format('buildnote %s %s', vim.fn.shellescape(filename), vim.fn.shellescape(output_path))
vim.cmd('silent !' .. command)
else
print('Error: File ' .. filename .. ' does not exist.')
end
end,
})

4
ftplugin/ocaml.lua Normal file
View file

@ -0,0 +1,4 @@
vim.opt.shiftwidth = 2
-- vim.keymap.set('n', '<space>cp', require('ocaml.mappings').dune_promote_file, { buffer = 0 })
--

145
ftplugin/python.lua Normal file
View file

@ -0,0 +1,145 @@
-- Set buffer-local options for Python files
vim.opt_local.expandtab = true -- Use spaces instead of tabs
vim.opt_local.commentstring = '# %s' -- Python comment format
vim.opt_local.shiftwidth = 4 -- Indent width
vim.opt_local.tabstop = 4 -- Tab width
vim.opt_local.softtabstop = 4 -- Soft tab width for alignment
vim.opt_local.fileformat = 'unix' -- Use Unix line endings
vim.opt_local.textwidth = 79 -- Maximum text width
vim.opt_local.colorcolumn = '80' -- Highlight column 80
local dap = require('dap')
local function get_python_path()
local cwd = vim.fn.getcwd()
if vim.env.VIRTUAL_ENV then
return vim.env.VIRTUAL_ENV .. '/bin/python' -- Use virtual environment if set
elseif vim.fn.executable(cwd .. '/venv/bin/python') == 1 then
return cwd .. '/venv/bin/python' -- Use project-specific venv
elseif vim.fn.executable(cwd .. '/.venv/bin/python') == 1 then
return cwd .. '/.venv/bin/python' -- Use hidden project venv
else
return 'python' -- Fallback to system Python
end
end
local function get_ipython_cmd()
local cwd = vim.fn.getcwd()
local venv = vim.env.VIRTUAL_ENV
if not venv then
if vim.fn.isdirectory(cwd .. '/.venv') == 1 then
venv = cwd .. '/.venv'
elseif vim.fn.isdirectory(cwd .. '/venv') == 1 then
venv = cwd .. '/venv'
end
end
if venv and vim.fn.executable(venv .. '/bin/ipython') == 1 then
return vim.fn.shellescape(venv .. '/bin/ipython')
end
local py = get_python_path()
if py:find('/') then
py = vim.fn.shellescape(py)
end
return py .. ' -m IPython'
end
local function get_ipython_argv()
local cwd = vim.fn.getcwd()
local venv = vim.env.VIRTUAL_ENV
if not venv then
if vim.fn.isdirectory(cwd .. '/.venv') == 1 then
venv = cwd .. '/.venv'
elseif vim.fn.isdirectory(cwd .. '/venv') == 1 then
venv = cwd .. '/venv'
end
end
if venv and vim.fn.executable(venv .. '/bin/ipython') == 1 then
return { venv .. '/bin/ipython' }
end
return { get_python_path(), '-m', 'IPython' }
end
vim.api.nvim_create_autocmd('LspAttach', {
group = vim.api.nvim_create_augroup('lsp_attach_disable_ruff_hover', { clear = true }),
callback = function(args)
local client = vim.lsp.get_client_by_id(args.data.client_id)
if client and client.name == 'ruff' then
client.server_capabilities.hoverProvider = false
end
end,
desc = 'Disable hover capability from Ruff',
})
require('dap-python').setup(get_python_path())
dap.configurations.python = {
{
type = 'python',
request = 'launch',
name = 'Launch Program',
program = '${file}',
console = 'integratedTerminal',
},
{
type = 'python',
request = 'launch',
name = 'Profile Memory',
program = '${file}',
args = { '--profile-memory' },
},
}
vim.keymap.set('n', '<leader>Rr', function()
local screen_width_percentage = 25
local function find_terminal_buffer()
for _, bufnr in ipairs(vim.api.nvim_list_bufs()) do
if vim.api.nvim_buf_is_loaded(bufnr) and vim.bo[bufnr].buftype == 'terminal' and vim.b[bufnr].python_repl == true then
return bufnr
end
end
return nil
end
local function toggle_terminal_window(bufnr)
for _, win in ipairs(vim.api.nvim_list_wins()) do
if vim.api.nvim_win_get_buf(win) == bufnr then
vim.api.nvim_win_hide(win)
return
end
end
vim.cmd('vsplit')
vim.api.nvim_win_set_buf(0, bufnr)
vim.cmd.wincmd('L')
vim.api.nvim_win_set_width(0, math.floor(vim.o.columns / (100 / screen_width_percentage)))
end
local function create_terminal()
vim.cmd('vnew')
vim.cmd.wincmd('L')
vim.api.nvim_win_set_width(0, math.floor(vim.o.columns / (100 / screen_width_percentage)))
vim.b.python_repl = true
local job_id = vim.fn.termopen(get_ipython_argv())
if job_id and job_id > 0 then
vim.g.slime_default_config = { jobid = job_id }
end
vim.cmd('startinsert')
end
local term_bufnr = find_terminal_buffer()
if term_bufnr then
local job_id = vim.b[term_bufnr].terminal_job_id
if job_id and job_id > 0 then
vim.g.slime_default_config = { jobid = job_id }
end
toggle_terminal_window(term_bufnr)
else
create_terminal()
end
end, { desc = 'Run/REPL: Toggle Python REPL' })

60
ftplugin/rust.lua Normal file
View file

@ -0,0 +1,60 @@
-- Set buffer-local options for Rust files
vim.opt_local.expandtab = true -- Use spaces instead of tabs
vim.opt_local.autoindent = true -- Maintain indentation levels
vim.opt_local.smartindent = true -- Smart indentation
vim.opt_local.shiftwidth = 4 -- Indent width
vim.opt_local.tabstop = 4 -- Tab width
vim.opt_local.softtabstop = 4 -- Soft tab width for alignment
vim.opt_local.textwidth = 80 -- Maximum text width
vim.opt_local.colorcolumn = '80' -- Highlight column 80
vim.keymap.set('n', '<leader>Rf', '<CMD>Cargo run<CR>', { desc = 'Run/REPL: Run (Cargo)', noremap = true, buffer = 0 })
vim.keymap.set('n', '<leader>Rb', '<CMD>Cargo check<CR>', { desc = 'Run/REPL: Build/Check (Cargo)', noremap = true, buffer = 0 })
local dap = require('dap')
local rust_tools = require('rust-tools')
local mason_registry = require('mason-registry')
local function get_codelldb_paths()
local codelldb_package = mason_registry.get_package('codelldb')
if not codelldb_package:is_installed() then
vim.notify('codelldb is not installed. Please install it via mason.nvim.', vim.log.levels.ERROR)
return nil, nil
end
local codelldb_path = codelldb_package:get_install_path()
local adapter = codelldb_path .. '/extension/adapter/codelldb'
local lib = codelldb_path .. '/extension/lldb/lib/liblldb.so'
return adapter, lib
end
local codelldb_adapter, codelldb_lib = get_codelldb_paths()
if codelldb_adapter and codelldb_lib then
rust_tools.setup({
tools = {
autosethints = true,
inlay_hints = {
show_parameter_hints = true,
parameter_hints_prefix = '<- ',
other_hints_prefix = '=> ',
},
},
server = {
on_attach = function(_, bufnr)
vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>dR', '<cmd>RustDebuggables<CR>', { noremap = true, silent = true })
vim.api.nvim_buf_set_keymap(bufnr, 'n', 'K', '<cmd>RustHoverActions<CR>', { noremap = true, silent = true })
end,
},
dap = {
adapter = require('rust-tools.dap').get_codelldb_adapter(codelldb_adapter, codelldb_lib),
},
})
end
dap.configurations.rust = {
{
type = 'rust',
request = 'launch',
name = 'Launch Program',
program = '${workspaceFolder}/target/debug/${workspaceFolderBasename}',
},
}

5
ftplugin/sh.lua Normal file
View file

@ -0,0 +1,5 @@
vim.opt_local.expandtab = false
vim.opt_local.shiftwidth = 2
vim.opt_local.softtabstop = 2
vim.opt_local.tabstop = 2
vim.opt_local.textwidth = 80

1
ftplugin/sql.lua Normal file
View file

@ -0,0 +1 @@
vim.opt_local.commentstring = '-- %s'

17
ftplugin/yaml.lua Normal file
View file

@ -0,0 +1,17 @@
-- Set indentation for YAML files
vim.bo.shiftwidth = 2
vim.bo.tabstop = 2
vim.bo.expandtab = true
-- Set text width to 80 to auto-break lines when formatting
vim.bo.textwidth = 80
vim.api.nvim_create_autocmd('BufWritePre', {
buffer = 0,
callback = function()
local first_line = vim.api.nvim_buf_get_lines(0, 0, 1, false)[1] or ''
if first_line ~= '---' then
vim.api.nvim_buf_set_lines(0, 0, 0, false, { '---' })
end
end,
})

26
init.lua Executable file
View file

@ -0,0 +1,26 @@
-- Install package manager
-- https://github.com/folke/lazy.nvim
local lazypath = vim.fn.stdpath('data') .. '/lazy/lazy.nvim'
if not vim.loop.fs_stat(lazypath) then
vim.fn.system({
'git',
'clone',
'--filter=blob:none',
'https://github.com/folke/lazy.nvim.git',
'--branch=stable', -- latest stable release
lazypath,
})
end
vim.opt.rtp:prepend(vim.env.LAZY or lazypath)
vim.cmd('filetype plugin on')
vim.g.mapleader = ' '
vim.g.maplocalleader = ' '
require('config.lazy')
require('config.autocmds')
require('config.options')
require('config.mappings')
require('config.utils')
require('config.themes')

67
lua/config/autocmds.lua Executable file
View file

@ -0,0 +1,67 @@
-- Auto-format on save
vim.cmd([[
augroup FormatOnSave
autocmd!
autocmd BufWritePre * lua vim.lsp.buf.format({ async = false })
augroup END
]])
-- Augroup for Highlight on yank
vim.cmd([[
augroup YankHighlight
autocmd!
autocmd TextYankPost * lua vim.hl.on_yank()
augroup END
]])
-- Remove trailing whitespace
vim.cmd([[
augroup RemoveTrailingWhitespace
autocmd!
autocmd BufWritePre * %s/\s\+$//e
augroup END
]])
-- Append newline at EOF, excluding YAML files
vim.cmd([[
augroup append_newline_at_eof
autocmd!
autocmd BufWritePre * silent! if !empty(getline('$')) && getline('$') !~# '\n$' && &filetype != 'yaml' | call append(line('$'), '') | endif
augroup END
]])
local function augroup(name)
return vim.api.nvim_create_augroup('lazyvim_' .. name, { clear = true })
end
vim.api.nvim_create_autocmd('VimEnter', {
group = augroup('autoupdate'),
callback = function()
if require('lazy.status').has_updates() then
require('lazy').update({ show = false })
end
end,
})
vim.api.nvim_create_autocmd('User', {
pattern = 'LazyCheck',
-- pattern = "LazyVimStarted",
desc = 'Update lazy.nvim plugins',
callback = function()
vim.schedule(function()
require('lazy').sync({ wait = false, show = false })
end)
end,
})
vim.api.nvim_create_autocmd('TermOpen', {
pattern = '*',
group = vim.api.nvim_create_augroup('custom-term-open', { clear = true }),
desc = 'Automatically start insert mode in terminal buffers',
callback = function()
vim.cmd('startinsert')
vim.cmd('setlocal nonumber norelativenumber')
vim.cmd('normal! G')
vim.cmd('tnoremap <esc><esc> <c-\\><c-n>')
end,
})

37
lua/config/lazy.lua Executable file
View file

@ -0,0 +1,37 @@
local opts = {
git = { log = { '--since=3 days ago' } },
ui = { custom_keys = { false } },
colors = { themes = { 'monokai' } },
checker = {
enabled = true,
-- notify = false,
},
performance = {
rtp = {
disabled_plugins = {
'gzip',
'tarPlugin',
'tohtml',
'tutor',
'zipPlugin',
},
},
},
change_detection = {
notify = false,
},
rocks = { enabled=false },
}
require('lazy').setup({
-- Git related plugins
'tpope/vim-fugitive',
'tpope/vim-rhubarb',
-- Detect tabstop and shiftwidth automatically
-- 'tpope/vim-sleuth',
{
import = 'custom.plugins',
exclude = 'custom.plugins.mason',
},
}, opts)

162
lua/config/mappings.lua Executable file
View file

@ -0,0 +1,162 @@
local utils = require('config.utils')
-- Basic Keymaps
-- Keymaps for better default experience
-- See `:help vim.keymap.set()`
vim.keymap.set({ 'n', 'v' }, '<Space>', '<Nop>', { silent = true })
-- vim.keymap.set('n', '<leader>pv', vim.cmd.Ex, { desc = "[P]roject [V]iew" })
vim.keymap.set('n', '<C-c>', '<ESC><ESC>', { silent = true })
vim.keymap.set('n', '<Esc>', '<cmd>nohlsearch<CR>', { silent = true })
-- Remap for dealing with word wrap
vim.keymap.set('n', 'k', "v:count == 0 ? 'gk' : 'k'", { expr = true, silent = true })
vim.keymap.set('n', 'j', "v:count == 0 ? 'gj' : 'j'", { expr = true, silent = true })
-- Move lines
vim.keymap.set('v', 'J', ":m '>+1<CR>gv=gv", { silent = true })
vim.keymap.set('v', 'K', ":m '<-2<CR>gv=gv", { silent = true })
vim.keymap.set('n', '>', '>gv', { silent = true })
vim.keymap.set('n', '<', '<gv', { silent = true })
-- Miscellaneous Navigation Keymaps
vim.keymap.set('n', 'J', 'mzj`z')
vim.keymap.set('n', '<c-d>', '<C-d>zz', { desc = 'Half Page Jumping Up' })
vim.keymap.set('n', '<c-u>', '<C-u>zz', { desc = 'Half Page Jumping Down' })
vim.keymap.set('n', 'n', 'nzzzv', { noremap = true, silent = true })
vim.keymap.set('n', 'N', 'Nzzzv', { noremap = true, silent = true })
vim.keymap.set('n', '<leader>n', function()
vim.o.hlsearch = not vim.o.hlsearch
end, { desc = 'Toggle Search Highlight' })
vim.api.nvim_set_keymap('n', 'gp', '<Nop>', { noremap = true, silent = true })
vim.keymap.set('n', '<C-k>', '<cmd>cnext<CR>zz')
vim.keymap.set('n', '<C-j>', '<cmd>cprev<CR>zz')
vim.keymap.set('n', ']q', '<cmd>lnext<CR>zz', { desc = 'Location List Next' })
vim.keymap.set('n', '[q', '<cmd>lprev<CR>zz', { desc = 'Location List Prev' })
-- Buffer Navigation Keymaps
vim.keymap.set('n', '<leader>bn', '<cmd>bnext<CR>zz', { desc = 'Quick Nav Buf Next' })
vim.keymap.set('n', '<leader>bp', '<cmd>bprev<CR>zz', { desc = 'Quick Nav Buf Prev' })
vim.keymap.set('n', '<leader>bd', '<cmd>bdelete<CR>', { desc = 'Quick Nav Buf Delete' })
vim.keymap.set('n', '<leader>bs', '<cmd>split<CR>', { desc = 'Openn Buf Horizontal Split' })
vim.keymap.set('n', '<leader>bv', '<cmd>vsp<CR>', { desc = 'Open Buf Vertical Split' })
-- vim.keymap.set('n', '<leader>bt', function()
-- vim.cmd.vnew()
-- vim.cmd.term()
-- vim.cmd.wincmd('J')
-- vim.api.nvim_win_set_height(0, 15)
-- end, { desc = 'Open Buf in Terminal' })
-- -- open terminal for R and Python
-- vim.keymap.set('n', '<leader>bR', '<cmd>terminal R<CR>', { desc = 'Open R Terminal' })
-- vim.keymap.set('n', '<leader>bP', '<cmd>terminal python<CR>', { desc = 'Open Python Terminal' })
-- Editing Keymaps
vim.keymap.set('x', '<leader>p', [["_dP"]], { desc = 'Paste without register' })
vim.keymap.set({ 'n', 'v' }, '<leader>D', [["_d"]], { desc = 'Delete without register' })
vim.keymap.set({ 'n', 'v' }, '<leader>y', '"+y', { desc = 'Copy to + register' })
vim.keymap.set('n', '<leader>Y', '"+Y')
-- replace current word in current scope
vim.keymap.set(
'n',
'<leader>rw',
':%s/\\<<C-r><C-w>\\>/<C-r><C-w>/gI<Left><Left><Left>',
{ desc = '[R]eplace Current [W]ord in Current Scope' }
)
-- replace current word in file scope
vim.keymap.set(
'n',
'<leader>rW',
':%s/\\<<C-r><C-w>\\>/<C-r><C-w>/gI<Left><Left><Left>',
{ desc = '[R]eplace Current [W]ord in File Scope' }
)
-- Open vertical split pane
-- File Management Keymaps
vim.keymap.set('n', '<C-f>', '<cmd>silent !tmux neww $HOME/.local/bin/tmux_sessionizer<CR>', { desc = 'Open Session' })
vim.keymap.set('n', '<leader>fx', '<cmd>!chmod +x %<CR>', { desc = 'Set Current File to Executable', silent = true })
-- Telescope Keymaps
-- See `:help telescope.builtin`
local builtin = require('telescope.builtin')
vim.keymap.set('n', '<leader>?', builtin.oldfiles, { desc = '[?] Find recently opened files' })
vim.keymap.set('n', '<leader><space>', builtin.buffers, { desc = '[ ] Find existing buffers' })
vim.keymap.set('n', '<leader>/', function()
builtin.current_buffer_fuzzy_find(require('telescope.themes').get_dropdown({ winblend = 10, previewer = false }))
end, { desc = '[/] Fuzzily search in current buffer' })
vim.keymap.set('n', '<leader>gf', builtin.git_files, { desc = 'Search [G]it [F]iles' })
vim.keymap.set('n', '<leader>gb', builtin.git_branches, { desc = 'Search [G]it [B]ranches' })
vim.keymap.set('n', '<leader>gc', builtin.git_commits, { desc = 'Search [G]it [C]ommits' })
vim.keymap.set('n', '<leader>sf', builtin.find_files, { desc = '[S]earch [F]iles' })
vim.keymap.set({ 'n', 'v' }, '<leader>sh', function()
local query = utils.get_search_query()
builtin.help_tags({ search = query, initial_mode = 'insert', default_text = query })
end, { desc = '[S]earch [H]elp' })
vim.keymap.set({ 'n', 'v' }, '<leader>sw', function()
local query = utils.get_search_query()
builtin.grep_string({ search = query, initial_mode = 'insert', default_text = query })
end, { desc = '[S]earch current [W]ord' })
vim.keymap.set('n', '<leader>sp', function()
builtin.grep_string({ search = vim.fn.input('Grep Search > ') })
end, { desc = '[S]earch [P]roject' })
vim.keymap.set('n', '<leader>sG', builtin.live_grep, { desc = '[S]earch by [G]rep' })
vim.keymap.set('n', '<leader>sg', ':LiveGrepGitRoot<cr>', { desc = '[S]earch by [G]rep on Git Root' })
vim.keymap.set('n', '<leader>sd', builtin.diagnostics, { desc = '[S]earch [D]iagnostics' })
vim.keymap.set('n', '<leader>sr', builtin.resume, { desc = '[S]earch [R]esume' })
-- Telescope config files
vim.keymap.set('n', '<leader>fc', function()
builtin.find_files({
cwd = vim.fn.stdpath('config'),
find_command = {
'fd',
'--type',
'f',
'--exclude',
'README.md',
'--exclude',
'LICENSE.md',
'--exclude',
'init.lua',
},
})
end, { desc = '[F]ind [C]onfig Files' })
vim.keymap.set('n', '<leader>fp', function()
builtin.find_files({
cwd = vim.fs.joinpath(vim.fn.stdpath('data'), 'lazy'),
})
end, { desc = '[F]ind [P]lugin Files' })
-- local runner = require("quarto.runner")
-- vim.keymap.set('n', '<leader>qrc', runner.run_cell, { desc = '[R]un [C]ell', silent = true })
-- vim.keymap.set('n', '<leader>qra', runner.run_above, { desc = '[R]un cell and [A]bove', silent = true })
-- vim.keymap.set('n', "<leader>qrA", runner.run_all, { desc = "run all cells", silent = true })
-- vim.keymap.set('n', "<leader>qrl", runner.run_line, { desc = "run line", silent = true })
-- vim.keymap.set('v', '<leader>qr', runner.run_range, { desc = "run visual range", silent = true })
-- vim.keymap.set('n', '<leader>qRA', function()
-- runner.run_all(true)
-- end, { desc = "run all cells of all languages", silent = true })
-- Refactoring Keymaps
-- vim.keymap.set({ "x" }, "<leader>re", [[<Esc><Cmd>lua require('refactoring').refactor('Extract Function')<CR>]],
-- { noremap = true, silent = true, expr = false, desc = "Extract Function" })
-- vim.keymap.set(
-- { "x" },
-- "<leader>rf", [[<Esc><Cmd>lua require('refactoring').refactor('Extract Function To File')<CR>]],
-- { noremap = true, silent = true, expr = false, desc = "Extract Function To File" }
--)
-- vim.keymap.set({ "x" }, "<leader>rv", [[<Esc><Cmd>lua require('refactoring').refactor('Extract Variable')<CR>]],
-- { noremap = true, silent = true, expr = false, desc = "Extract Variable" })
-- vim.keymap.set({ "n" }, "<leader>rI", [[<Cmd>lua require('refactoring').refactor('Inline Variable')<CR>]],
-- { noremap = true, silent = true, expr = false, desc = "Inline Variable" })
-- vim.keymap.set({ "n", "x" }, "<leader>ri", [[<Esc><Cmd>lua require('refactoring').refactor('Inline Variable')<CR>]],
-- { noremap = true, silent = true, expr = false, desc = "Inline Variable" })
--
-- vim.keymap.set({ "n" }, "<leader>rb", [[<Esc><Cmd>lua require('refactoring').refactor('Extract Block')<CR>]],
-- { noremap = true, silent = true, expr = false, desc = "Extract Block" })
-- vim.keymap.set({ "n" }, "<leader>rbf", [[<Esc><Cmd>lua require('refactoring').refactor('Extract Block To File')<CR>]],
-- { noremap = true, silent = true, expr = false, desc = "Extract Block To File" })

141
lua/config/options.lua Executable file
View file

@ -0,0 +1,141 @@
local opt = vim.opt
local g = vim.g
g.ftplugin_migrated_all = true
local opts = {
-- Change cursor in insert mode
guicursor = '',
-- set terminal tab title
title = true,
titlelen = 0,
-- titlestring = 'nvim %t (%-15.25F)%a%r%m',
titlestring = 'nvim %t (%-15.25f)%a%r%m',
-- Make line numbers default
relativenumber = true,
--Enable noshowmode
showmode = false,
-- Enable lazy redraw
lazyredraw = true,
-- Enable break indent
breakindent = true,
-- Indent Configuration
tabstop = 4,
softtabstop = 4,
shiftwidth = 4,
expandtab = true,
-- Disable line wrap
wrap = false,
-- Save undo history
swapfile = false,
backup = false,
undodir = vim.fn.stdpath('data') .. '/site/undodir',
undofile = true,
-- Searching Configuration
hlsearch = false,
incsearch = true,
-- Case-insensitive searching UNLESS \C or capital in search
ignorecase = true,
smartcase = true,
-- Decrease update time
updatetime = 50,
timeoutlen = 300,
-- Set completeopt to have a better completion experience
completeopt = 'menuone,noselect',
-- NOTE: You should make sure your terminal supports this
termguicolors = true,
scrolloff = 10,
pyxversion = 3,
-- Sets how neovim will display certain whitespace characters in the editor.
-- See :help 'list'
-- and :help 'listchars'
list = true,
listchars = { tab = ' ', trail = '·', nbsp = '' },
-- Preview substitutions live, as you type!
inccommand = 'split',
}
for k, v in pairs(opts) do
opt[k] = v
end
local win_local = {
signcolumn = 'yes',
number = true,
}
for k, v in pairs(win_local) do
vim.wo[k] = v
end
-- Disable built-in plugins
local disabled_built_ins = {
'2html_plugin',
'getscript',
'getscriptPlugin',
'gzip',
'logipat',
'matchit',
-- "netrw",
'netrwFileHandlers',
'loaded_remote_plugins',
'loaded_tutor_mode_plugin',
-- "netrwPlugin",
-- "netrwSettings",
'rrhelper',
'spellfile_plugin',
'tar',
'tarPlugin',
'vimball',
'vimballPlugin',
'zip',
'zipPlugin',
'matchparen',
}
for _, plugin in pairs(disabled_built_ins) do
g['loaded_' .. plugin] = 1
end
-- Improve Neovim startup
local global_let_opts = {
loaded_python_provider = 0,
loaded_python3_provider = 0,
python_host_skip_check = 1,
python3_host_skip_check = 1,
python3_host_prog = '/usr/local/bin/python3',
EditorConfig_core_mode = 'external_command',
matchparen_timeout = 20,
matchparen_insert_timeout = 20,
}
for k, v in pairs(global_let_opts) do
g[k] = v
end
opt.formatoptions = 'l'
opt.formatoptions = opt.formatoptions
- 'a' -- Auto formatting is BAD.
- 't' -- Don't auto format my code. I got linters for that.
+ 'c' -- In general, I like it when comments respect textwidth
- 'o' -- O and o, don't continue comments
+ 'r' -- But do continue when pressing enter.
+ 'n' -- Indent past the formatlistpat, not underneath it.
+ 'j' -- Auto-remove comments if possible.
- '2' -- I'm not in gradeschool anymore
opt.iskeyword:append('_')

0
lua/config/themes.lua Executable file
View file

23
lua/config/utils.lua Executable file
View file

@ -0,0 +1,23 @@
-- Function to get the current visual selection
local function get_visual_selection()
vim.cmd('noau normal! "vy"')
local text = vim.fn.getreg('v')
-- optional: clear register v
-- vim.fn.setreg('v', '')
text = text:gsub('\n$', '') -- remove trailing newline
return text
end
-- Function to get the current search query
local function get_search_query()
local word_under_cursor = vim.fn.expand('<cword>')
local visual_selection = get_visual_selection() -- call local function directly
return visual_selection ~= '' and visual_selection or word_under_cursor
end
return {
get_visual_selection = get_visual_selection,
get_search_query = get_search_query,
}

17
lua/custom/plugins/atac.lua Executable file
View file

@ -0,0 +1,17 @@
return {
'NachoNievaG/atac.nvim',
dependencies = { 'akinsho/toggleterm.nvim' },
config = function()
require('toggleterm').setup({
open_mapping = [[<c-\>]],
hide_numbers = true,
shade_terminals = true,
start_in_insert = true,
persist_size = true,
close_on_exit = true,
})
require('atac').setup({
dir = '~/Documents/projects/', -- By default, the dir will be set as /tmp/atac
})
end,
}

View file

@ -0,0 +1,66 @@
-- Define the function to set custom highlights for both themes
local function set_lsp_highlights(mode)
local hl = vim.api.nvim_set_hl
-- Shared diagnostic groups
local diagnostic_groups = {
'DiagnosticVirtualTextError',
'DiagnosticVirtualTextWarn',
'DiagnosticVirtualTextInfo',
'DiagnosticVirtualTextHint',
'DiagnosticUnderlineError',
'DiagnosticUnderlineWarn',
'DiagnosticUnderlineInfo',
'DiagnosticUnderlineHint',
}
if mode == 'dark' then
local fg = 'NONE'
local bg = '#272822'
local comment = '#75715e'
local line_nr = '#90908a'
for _, group in ipairs(diagnostic_groups) do
hl(0, group, { fg = fg, bg = bg, underline = false })
end
hl(0, 'TreesitterContext', { bg = bg })
hl(0, 'TreesitterContextLineNumber', { fg = line_nr })
hl(0, 'TreesitterContextSeparator', { fg = comment })
elseif mode == 'light' then
local bg = '#fdf6e3'
local fg = '#657b83'
local comment = '#586e75'
hl(0, 'LspDocumentHighlight', { bg = bg, fg = fg, underline = false })
hl(0, 'DiagnosticVirtualTextError', { fg = '#dc322f' })
hl(0, 'DiagnosticVirtualTextWarn', { fg = '#b58900' })
hl(0, 'DiagnosticVirtualTextInfo', { fg = '#268bd2' })
hl(0, 'DiagnosticVirtualTextHint', { fg = '#2aa198' })
hl(0, 'TreesitterContext', { bg = 'NONE' })
hl(0, 'TreesitterContextLineNumber', { fg = comment })
hl(0, 'TreesitterContextSeparator', { fg = comment })
end
end
return {
'f-person/auto-dark-mode.nvim',
opts = {
update_interval = 2000,
set_dark_mode = function()
vim.api.nvim_set_option_value('background', 'dark', {})
vim.cmd('colorscheme monokai_soda')
-- Apply custom highlight settings for Monokai
set_lsp_highlights('dark')
end,
set_light_mode = function()
vim.api.nvim_set_option_value('background', 'light', {})
vim.cmd('colorscheme solarized')
-- Apply custom highlight settings for Solarized
set_lsp_highlights('light')
end,
},
}

View file

@ -0,0 +1,12 @@
return {
'windwp/nvim-autopairs',
dependencies = { 'hrsh7th/nvim-cmp' },
event = 'InsertEnter',
config = function()
require('nvim-autopairs').setup({})
-- If you want to automatically add `(` after selecting a function or method
local cmp_autopairs = require('nvim-autopairs.completion.cmp')
local cmp = require('cmp')
cmp.event:on('confirm_done', cmp_autopairs.on_confirm_done())
end,
}

143
lua/custom/plugins/cmp.lua Executable file
View file

@ -0,0 +1,143 @@
return {
'hrsh7th/nvim-cmp',
event = { 'InsertEnter', 'CmdlineEnter' },
dependencies = {
-- Core snippet engine and integration
{ 'L3MON4D3/LuaSnip' },
{ 'saadparwaiz1/cmp_luasnip' },
-- LSP support
{ 'hrsh7th/cmp-nvim-lsp' },
-- Predefined snippets, lazy-loaded
{ 'rafamadriz/friendly-snippets' },
-- Additional sources
{ 'hrsh7th/cmp-path' },
{ 'hrsh7th/cmp-buffer' }, -- Will be filtered later
-- Cmdline & git
{ 'hrsh7th/cmp-cmdline' },
{ 'petertriho/cmp-git', ft = { 'gitcommit' } },
-- UI enhancement
{ 'onsails/lspkind-nvim' },
},
config = function()
local cmp = require('cmp')
local luasnip = require('luasnip')
local lspkind = require('lspkind')
-- Load only selected snippets
require('luasnip.loaders.from_vscode').lazy_load({})
vim.opt.completeopt = { 'menu', 'menuone', 'noselect' }
luasnip.config.setup({
history = true,
updateevents = 'TextChanged,TextChangedI',
})
-- Precompute mappings for insert and command mode
local insert_mappings = {
['<C-n>'] = cmp.mapping.select_next_item(),
['<C-p>'] = cmp.mapping.select_prev_item(),
['<C-b>'] = cmp.mapping.scroll_docs(-4),
['<C-f>'] = cmp.mapping.scroll_docs(4),
['<Tab>'] = cmp.mapping(function(fallback)
if cmp.visible() then
cmp.select_next_item()
elseif luasnip.expand_or_jumpable() then
luasnip.expand_or_jump()
else
fallback()
end
end, { 'i', 's', 'c' }),
['<S-Tab>'] = cmp.mapping(function(fallback)
if cmp.visible() then
cmp.select_prev_item()
elseif luasnip.jumpable(-1) then
luasnip.jump(-1)
else
fallback()
end
end, { 'i', 's', 'c' }),
['<CR>'] = cmp.mapping.confirm({ select = false }),
}
local insert_sources = {
{ name = 'nvim_lsp', priority = 1000 },
{ name = 'luasnip', priority = 900 },
{ name = 'path', priority = 750 },
{ name = 'buffer', priority = 500, keyword_length = 5, max_item_count = 50 },
}
cmp.setup({
snippet = {
expand = function(args)
luasnip.lsp_expand(args.body)
end,
},
mapping = insert_mappings,
sources = insert_sources,
formatting = {
fields = { 'abbr', 'kind', 'menu' },
expandable_indicator = false,
format = function(entry, vim_item)
if entry.source.name == 'nvim_lsp' then
return lspkind.cmp_format({
mode = 'symbol_text',
maxwidth = 50,
ellipsis_char = '...',
menu = {
nvim_lsp = '[LSP]',
luasnip = '[Snip]',
buffer = '[Buffer]',
path = '[Path]',
},
})(entry, vim_item)
end
return vim_item
end,
},
window = {
completion = cmp.config.window.bordered(),
documentation = cmp.config.window.bordered(),
},
performance = {
filtering_context_budget = 5,
async_budget = 5,
confirm_resolve_timeout = 100,
max_view_entries = 20,
debounce = 60,
throttle = 30,
fetching_timeout = 200,
},
})
-- Cmdline setup
cmp.setup.cmdline({ '/', '?' }, {
mapping = insert_mappings,
sources = { { name = 'buffer', keyword_length = 5 } },
})
cmp.setup.cmdline(':', {
mapping = insert_mappings,
sources = { { name = 'path' }, { name = 'cmdline' } },
window = {
documentation = cmp.config.window.bordered({
winhighlight = 'Normal:Normal,FloatBorder:FloatBorder,CursorLine:Visual,Search:None',
border = 'rounded',
}),
},
})
-- Git commit
cmp.setup.filetype('gitcommit', {
sources = {
{ name = 'git', priority = 900 },
{ name = 'buffer', keyword_length = 5 },
},
})
end,
}

View file

@ -0,0 +1,4 @@
return {
'numToStr/Comment.nvim',
opts = {},
}

View file

@ -0,0 +1,28 @@
return {
'nvim-treesitter/nvim-treesitter-context',
event = 'BufReadPost',
config = function()
require('treesitter-context').setup({
max_lines = 3,
multiwindow = false,
multiline_threshold = 1,
trim_scope = 'inner',
mode = 'cursor', -- faster than 'cursor'
separator = '',
on_attach = function(buf)
-- disable for large files
if vim.api.nvim_buf_line_count(buf) > 3000 then
return false
end
-- disable for specific filetypes
local disabled = { 'markdown', 'text', 'help', 'json', 'yaml' }
if vim.tbl_contains(disabled, vim.bo[buf].filetype) then
return false
end
return true
end,
})
vim.keymap.set('n', '<leader>uc', '<cmd>TSContext toggle<cr>')
end,
}

View file

@ -0,0 +1,43 @@
-- Copilot Chat (UI + prompts for Copilot)
return {
'CopilotC-Nvim/CopilotChat.nvim',
cmd = {
'CopilotChat',
'CopilotChatClose',
'CopilotChatExplain',
'CopilotChatReview',
'CopilotChatTests',
'CopilotChatRefactor',
'CopilotChatOptimize',
'CopilotChatDocs',
'CopilotChatToggle',
},
keys = {
{ '<leader>C', '<cmd>CopilotChat<cr>', desc = 'Open CopilotChat' },
{ '<leader>Cq', '<cmd>CopilotChatClose<cr>', desc = 'Close CopilotChat' },
{ '<leader>Ce', '<cmd>CopilotChatExplain<cr>', desc = 'Explain code', mode = { 'n', 'v' } },
{ '<leader>Cr', '<cmd>CopilotChatReview<cr>', desc = 'Review code', mode = { 'n', 'v' } },
{ '<leader>Ct', '<cmd>CopilotChatTests<cr>', desc = 'Generate tests', mode = { 'n', 'v' } },
{ '<leader>Cf', '<cmd>CopilotChatRefactor<cr>', desc = 'Refactor code', mode = { 'n', 'v' } },
{ '<leader>Co', '<cmd>CopilotChatOptimize<cr>', desc = 'Optimize code', mode = { 'n', 'v' } },
{ '<leader>Cd', '<cmd>CopilotChatDocs<cr>', desc = 'Generate docs', mode = { 'n', 'v' } },
{ '<leader>Cp', '<cmd>CopilotChatToggle<cr>', desc = 'Toggle CopilotChat' },
},
build = 'make tiktoken',
opts = {
debug = false,
show_help = true,
prompts = {
Explain = 'Please explain how the following code works.',
Review = 'Please review the following code and provide suggestions for improvement.',
Tests = 'Please explain how the selected code works, then generate unit tests for it.',
Refactor = 'Please refactor the following code to improve its clarity and readability.',
Optimize = 'Please optimize the following code for efficiency and performance.',
Docs = 'Please generate documentation for the following code.',
},
},
dependencies = {
'nvim-lua/plenary.nvim',
'zbirenbaum/copilot.lua', -- make sure copilot is available
},
}

18
lua/custom/plugins/copilot.lua Executable file
View file

@ -0,0 +1,18 @@
-- GitHub Copilot base plugin
return {
'zbirenbaum/copilot.lua',
cmd = 'Copilot',
event = 'InsertEnter',
opts = {
node_cmd = vim.fn.executable('node') == 1 and vim.fn.exepath('node') or 'node',
suggestion = {
auto_trigger = true,
keymap = {
accept_word = '<M-u>',
accept_line = '<M-i>',
-- next = '<M-[>',
-- previous = '<M-]>',
},
},
},
}

17
lua/custom/plugins/dadbod.lua Executable file
View file

@ -0,0 +1,17 @@
return {
'kristijanhusak/vim-dadbod-ui',
dependencies = {
{ 'tpope/vim-dadbod', lazy = true },
{ 'kristijanhusak/vim-dadbod-completion', ft = { 'sql', 'mysql', 'plsql' }, lazy = true }, -- Optional
},
cmd = {
'DBUI',
'DBUIToggle',
'DBUIAddConnection',
'DBUIFindBuffer',
},
init = function()
-- Your DBUI configuration
vim.g.db_ui_use_nerd_fonts = 1
end,
}

204
lua/custom/plugins/dap.lua Executable file
View file

@ -0,0 +1,204 @@
return {
-- Define language plugins at top level to prevent luarocks installation
{
'mfussenegger/nvim-dap-python',
ft = 'python',
rocks = { enabled = false },
},
{
'leoluz/nvim-dap-go',
ft = 'go',
rocks = { enabled = false },
},
{
'mfussenegger/nvim-dap',
dependencies = {
'rcarriga/nvim-dap-ui',
'nvim-neotest/nvim-nio',
{ 'thehamsta/nvim-dap-virtual-text', opts = {} },
'mfussenegger/nvim-dap-python',
'leoluz/nvim-dap-go',
'jay-babu/mason-nvim-dap.nvim',
},
config = function()
local dap = require('dap')
local dapui = require('dapui')
dapui.setup()
-- Mason handles debugger installation and configuration
require('mason-nvim-dap').setup({
automatic_installation = true,
ensure_installed = { 'codelldb', 'python', 'delve' },
handlers = {},
})
-- Python setup with proper path detection
local function get_python_path()
-- Check if we're in a virtual environment
local venv = os.getenv('VIRTUAL_ENV')
if venv then
local venv_python = venv .. '/bin/python'
if vim.fn.executable(venv_python) == 1 then
return venv_python
end
end
-- Fall back to system python3 or python
local python3 = vim.fn.exepath('python3')
if python3 ~= '' then
return python3
end
local python = vim.fn.exepath('python')
if python ~= '' then
return python
end
-- Last resort - use system default
return 'python3'
end
require('dap-python').setup(get_python_path())
-- Go setup (helper does the heavy lifting)
require('dap-go').setup()
-- C/C++ configurations
dap.configurations.c = {
{
name = 'Launch',
type = 'codelldb',
request = 'launch',
program = function()
return vim.fn.input('Path to executable: ', vim.fn.getcwd() .. '/', 'file')
end,
cwd = '${workspaceFolder}',
stopOnEntry = false,
},
{
name = 'Launch with ASan',
type = 'codelldb',
request = 'launch',
program = function()
return vim.fn.input('Path to executable: ', vim.fn.getcwd() .. '/', 'file')
end,
cwd = '${workspaceFolder}',
stopOnEntry = false,
env = { ASAN_OPTIONS = 'detect_leaks=1' },
},
}
dap.configurations.cpp = dap.configurations.c
-- Rust configuration
dap.configurations.rust = {
{
name = 'Launch',
type = 'codelldb',
request = 'launch',
program = function()
return vim.fn.input('Path to executable: ', vim.fn.getcwd() .. '/target/debug/', 'file')
end,
cwd = '${workspaceFolder}',
stopOnEntry = false,
},
}
-- Zig configuration
dap.configurations.zig = {
{
name = 'Launch',
type = 'codelldb',
request = 'launch',
program = function()
return vim.fn.input('Path to executable: ', vim.fn.getcwd() .. '/zig-out/bin/', 'file')
end,
cwd = '${workspaceFolder}',
stopOnEntry = false,
},
}
-- Auto-open/close UI
dap.listeners.after.event_initialized['dapui_config'] = dapui.open
dap.listeners.before.event_terminated['dapui_config'] = dapui.close
dap.listeners.before.event_exited['dapui_config'] = dapui.close
-- Breakpoint signs
vim.fn.sign_define('DapBreakpoint', { text = '🔴', texthl = '', linehl = '', numhl = '' })
vim.fn.sign_define('DapStopped', { text = '➡️', texthl = '', linehl = 'debugPC', numhl = '' })
end,
keys = {
{
'<leader>dc',
function()
require('dap').continue()
end,
desc = 'Debug: Continue',
},
{
'<leader>ds',
function()
require('dap').step_over()
end,
desc = 'Debug: Step Over',
},
{
'<leader>di',
function()
require('dap').step_into()
end,
desc = 'Debug: Step Into',
},
{
'<leader>do',
function()
require('dap').step_out()
end,
desc = 'Debug: Step Out',
},
{
'<leader>db',
function()
require('dap').toggle_breakpoint()
end,
desc = 'Debug: Toggle Breakpoint',
},
{
'<leader>dB',
function()
require('dap').set_breakpoint(vim.fn.input('Breakpoint condition: '))
end,
desc = 'Debug: Conditional Breakpoint',
},
{
'<leader>dr',
function()
require('dap').repl.toggle()
end,
desc = 'Debug: Toggle REPL',
},
{
'<leader>dl',
function()
require('dap').run_last()
end,
desc = 'Debug: Run Last',
},
{
'<leader>du',
function()
require('dapui').toggle()
end,
desc = 'Debug: Toggle UI',
},
{
'<leader>dt',
function()
require('dap').terminate()
end,
desc = 'Debug: Terminate',
},
},
ft = { 'python', 'go', 'rust', 'c', 'cpp', 'zig' },
},
}

View file

@ -0,0 +1,6 @@
return {
'sindrets/diffview.nvim',
dependencies = { 'nvim-lua/plenary.nvim' },
opts = {},
}

View file

@ -0,0 +1,88 @@
return {
'stevearc/conform.nvim',
dependencies = {
'nvim-lua/plenary.nvim',
'WhoIsSethDaniel/mason-tool-installer.nvim',
},
event = { 'BufReadPre', 'BufNewFile' },
opts = {
formatters = {
juliaformatter = {
command = 'julia',
args = {
'--project=' .. vim.fn.expand('~/.julia/environments/nvim-format'),
'--startup-file=no',
'--history-file=no',
'-e',
[[
using JuliaFormatter
print(format_text(read(stdin, String)))
]],
},
stdin = true,
},
},
formatters_by_ft = {
python = {
'ruff_fix',
'ruff_format',
'ruff_organize_imports',
},
yaml = { 'yamlfmt' },
sh = { 'shfmt' },
sql = { 'sqlfluff' },
lua = { 'stylua' },
json = { 'jq' },
julia = { 'juliaformatter' }, -- keep JuliaFormatter here
markdown = { 'prettierd', 'prettier' },
html = { 'prettierd' },
css = { 'prettierd' },
javascript = { 'prettierd' },
typescript = { 'prettierd' },
},
-- Fallback setup
format_on_save = function(bufnr)
if vim.bo[bufnr].filetype == 'julia' then
return
end
return {
timeout_ms = 2000,
lsp_fallback = true,
}
end,
notify_on_error = true,
async = true,
},
config = function(_, opts)
-- Setup Conform
require('conform').setup(opts)
-- Auto-install formatters via Mason
local all_formatters = {}
for _, formatters in pairs(opts.formatters_by_ft) do
for _, f in ipairs(formatters) do
all_formatters[f] = true
end
end
local exclude = {
ruff_fix = true,
ruff_format = true,
ruff_organize_imports = true,
juliaformatter = true, -- exclude JuliaFormatter from Mason (install via Julia)
}
local tools = vim.tbl_filter(function(tool)
return not exclude[tool]
end, vim.tbl_keys(all_formatters))
require('mason-tool-installer').setup({
ensure_installed = tools,
auto_update = false,
run_on_start = true,
})
end,
}

46
lua/custom/plugins/fugitive.lua Executable file
View file

@ -0,0 +1,46 @@
return {
'tpope/vim-fugitive',
config = function()
-- General key mappings for Fugitive
vim.keymap.set('n', '<leader>gs', vim.cmd.Git, { desc = 'Open Git status' })
-- Create an autocommand group for Fugitive-specific settings
local fugitive_augroup = vim.api.nvim_create_augroup('fugitive', { clear = true })
-- Set up autocommands for Fugitive buffers
vim.api.nvim_create_autocmd('BufWinEnter', {
group = fugitive_augroup,
pattern = '*',
callback = function()
if vim.bo.filetype ~= 'fugitive' then
return
end
local bufnr = vim.api.nvim_get_current_buf()
local opts = { buffer = bufnr, remap = false }
-- Key mappings specific to Fugitive buffers
vim.keymap.set('n', '<leader>gp', function()
vim.cmd.Git('push')
end, opts)
vim.keymap.set('n', '<leader>gP', function()
vim.cmd.Git('pull --rebase')
end, opts)
vim.keymap.set('n', '<leader>gU', ':Git push -u origin ', opts)
end,
})
-- Additional key mappings for resolving Git conflicts
vim.keymap.set('n', 'gu', '<cmd>diffget //2<CR>', { desc = 'Get diff for version 2' })
vim.keymap.set('n', 'gh', '<cmd>diffget //3<CR>', { desc = 'Get diff for version 3' })
-- Create a custom user command for Git operations
vim.api.nvim_create_user_command('Git', function(params)
vim.cmd('Git ' .. params.args)
end, { nargs = '*' })
end,
cond = function()
-- Conditional loading based on the presence of a Git repository
return vim.fn.isdirectory('.git') == 1
end,
}

45
lua/custom/plugins/gitsigns.lua Executable file
View file

@ -0,0 +1,45 @@
return {
'lewis6991/gitsigns.nvim',
opts = {
-- Git sign characters
signs = {
add = { text = '+' },
change = { text = '~' },
delete = { text = '_' },
topdelete = { text = '' },
changedelete = { text = '~' },
},
-- Function called when plugin attaches to a buffer
on_attach = function(bufnr)
-- Always show the sign column
vim.opt.signcolumn = 'yes'
-- Keybindings
local gs = require('gitsigns')
vim.keymap.set('n', '<leader>hp', gs.preview_hunk, {
buffer = bufnr,
desc = 'Preview git hunk',
})
vim.keymap.set({ 'n', 'v' }, ']c', function()
if vim.wo.diff then
return ']c'
end
vim.schedule(function()
gs.next_hunk()
end)
return '<Ignore>'
end, { expr = true, buffer = bufnr, desc = 'Jump to next hunk' })
vim.keymap.set({ 'n', 'v' }, '[c', function()
if vim.wo.diff then
return '[c'
end
vim.schedule(function()
gs.prev_hunk()
end)
return '<Ignore>'
end, { expr = true, buffer = bufnr, desc = 'Jump to previous hunk' })
end,
},
}

102
lua/custom/plugins/harpoon.lua Executable file
View file

@ -0,0 +1,102 @@
return {
'theprimeagen/harpoon',
branch = 'harpoon2',
dependencies = {
'nvim-lua/plenary.nvim',
-- 'nvim-telescope/telescope.nvim',
},
config = function()
local harpoon = require('harpoon')
-- local actions = require('telescope.actions')
-- local action_state = require('telescope.actions.state')
-- local conf = require('telescope.config').values
harpoon:setup({
settings = {
save_on_toggle = true,
sync_on_ui_close = true,
key = function()
return vim.loop.cwd() or 'global'
end,
},
})
-- Telescope integration
-- local function toggle_telescope()
-- local list = harpoon:list()
-- local file_paths = {}
--
-- for _, item in ipairs(list.items) do
-- table.insert(file_paths, item.value)
-- end
--
-- require('telescope.pickers')
-- .new({}, {
-- prompt_title = 'Harpoon',
-- finder = require('telescope.finders').new_table({
-- results = file_paths,
-- }),
-- previewer = false,
-- sorter = conf.generic_sorter({}),
-- layout_config = {
-- width = 0.5,
-- height = 0.5,
-- prompt_position = 'top',
-- },
-- layout_strategy = 'vertical',
-- attach_mappings = function(prompt_bufnr, map)
-- map('i', '<C-d>', function()
-- local selection = action_state.get_selected_entry()
-- if not selection then
-- return
-- end
--
-- local target = selection[1]
-- for _, item in ipairs(harpoon:list().items) do
-- if item.value == target then
-- harpoon:list():remove(item)
-- break
-- end
-- end
-- actions.close(prompt_bufnr)
-- toggle_telescope()
-- end)
-- return true
-- end,
-- })
-- :find()
-- end
vim.keymap.set('n', '<leader>a', function()
if vim.fn.expand('%:p'):sub(1, 6) == 'oil://' then
return
end
harpoon:list():add()
end, { desc = 'Harpoon: Add file to list (if not already present)' })
vim.keymap.set('n', '<C-e>', function()
harpoon.ui:toggle_quick_menu(harpoon:list())
end, { desc = 'Harpoon: Toggle quick menu' })
vim.keymap.set('n', '<C-h>', function()
harpoon:list():select(1)
end)
vim.keymap.set('n', '<C-j>', function()
harpoon:list():select(2)
end)
vim.keymap.set('n', '<C-k>', function()
harpoon:list():select(3)
end)
vim.keymap.set('n', '<C-l>', function()
harpoon:list():select(4)
end)
vim.keymap.set('n', '<C-h>', function()
harpoon:list():prev()
end)
vim.keymap.set('n', '<C-l>', function()
harpoon:list():next()
end)
end,
}

View file

@ -0,0 +1,104 @@
return {
-- {
-- 'vhyrro/luarocks.nvim',
-- priority = 1001,
-- opts = {
-- rocks = { 'magick' },
-- },
-- event = 'VeryLazy', -- Adjust this based on your needs
-- },
-- {
-- 'willothy/wezterm.nvim',
-- config = true,
-- event = 'BufWinEnter', -- Or another appropriate event
-- },
-- {
-- '3rd/image.nvim',
-- enabled = true,
-- commit = 'deb158d',
-- dev = false,
-- ft = { 'markdown', 'quarto', 'vimwiki' },
-- config = function()
-- local image = require 'image'
-- image.setup {
-- backend = 'wezterm',
-- integrations = {
-- markdown = {
-- enabled = true,
-- only_render_image_at_cursor = true,
-- filetypes = { 'markdown', 'vimwiki', 'quarto' },
-- },
-- },
-- editor_only_render_when_focused = false,
-- window_overlap_clear_enabled = true,
-- tmux_show_only_in_active_window = true,
-- window_overlap_clear_ft_ignore = { 'cmp_menu', 'cmp_docs', 'scrollview', 'scrollview_sign' },
-- max_width = nil,
-- max_height = nil,
-- max_width_window_percentage = nil,
-- max_height_window_percentage = 30,
-- kitty_method = 'normal',
-- }
--
-- local function clear_all_images()
-- local bufnr = vim.api.nvim_get_current_buf()
-- local images = image.get_images { buffer = bufnr }
-- for _, img in ipairs(images) do
-- img:clear()
-- end
-- end
--
-- local function get_image_at_cursor(buf)
-- local images = image.get_images { buffer = buf }
-- local row = vim.api.nvim_win_get_cursor(0)[1] - 1
-- for _, img in ipairs(images) do
-- if img.geometry ~= nil and img.geometry.y == row then
-- local og_max_height = img.global_state.options.max_height_window_percentage
-- img.global_state.options.max_height_window_percentage = nil
-- return img, og_max_height
-- end
-- end
-- return nil
-- end
--
-- local create_preview_window = function(img, og_max_height)
-- local buf = vim.api.nvim_create_buf(false, true)
-- local win_width = vim.api.nvim_get_option_value('columns', {})
-- local win_height = vim.api.nvim_get_option_value('lines', {})
-- local win = vim.api.nvim_open_win(buf, true, {
-- relative = 'editor',
-- style = 'minimal',
-- width = win_width,
-- height = win_height,
-- row = 0,
-- col = 0,
-- zindex = 1000,
-- })
-- vim.keymap.set('n', 'q', function()
-- vim.api.nvim_win_close(win, true)
-- img.global_state.options.max_height_window_percentage = og_max_height
-- end, { buffer = buf })
-- return { buf = buf, win = win }
-- end
--
-- local handle_zoom = function(bufnr)
-- local img, og_max_height = get_image_at_cursor(bufnr)
-- if img == nil then
-- return
-- end
--
-- local preview = create_preview_window(img, og_max_height)
-- image.hijack_buffer(img.path, preview.win, preview.buf)
-- end
--
-- vim.keymap.set('n', '<leader>io', function()
-- local bufnr = vim.api.nvim_get_current_buf()
-- handle_zoom(bufnr)
-- end, { buffer = true, desc = 'image [o]pen' })
--
-- vim.keymap.set('n', '<leader>ic', clear_all_images, { desc = 'image [c]lear' })
-- end,
-- },
--
}

24
lua/custom/plugins/indent.lua Executable file
View file

@ -0,0 +1,24 @@
local highlight = {
'Whitespace',
'Function',
}
return {
-- Add indentation guides even on blank lines
'lukas-reineke/indent-blankline.nvim',
main = 'ibl',
opts = {
indent = {
highlight = highlight,
char = '',
},
whitespace = {
highlight = highlight,
remove_blankline_trail = true,
},
scope = {
enabled = true,
exclude = { language = { 'vim', 'lua', 'go', 'python', 'rust', 'sh', 'json', 'yaml', 'toml', 'markdown' } },
},
},
}

View file

@ -0,0 +1,67 @@
return {
'goerz/jupytext.vim',
lazy = false,
config = function()
vim.g.jupytext_fmt = 'py:percent'
vim.g.jupytext_enable = 1
vim.g.jupytext_pairing = 1
local jupytext_bin = vim.fn.exepath('jupytext')
if jupytext_bin ~= nil and jupytext_bin ~= '' then
vim.g.jupytext_command = jupytext_bin
else
local preferred_python3 = '/opt/homebrew/bin/python3'
local python3_bin = preferred_python3
if vim.fn.executable(preferred_python3) ~= 1 then
python3_bin = vim.fn.exepath('python3')
end
if python3_bin ~= nil and python3_bin ~= '' then
vim.g.jupytext_command = python3_bin .. ' -m jupytext'
else
vim.schedule(function()
vim.notify('Jupytext: no `jupytext` or `python3` found in PATH. Install jupytext (e.g. `/opt/homebrew/bin/python3 -m pip install --user jupytext`) or set `vim.g.jupytext_command`.', vim.log.levels.WARN)
end)
end
end
local jupytext_group = vim.api.nvim_create_augroup('custom_jupytext', { clear = true })
vim.api.nvim_create_autocmd('BufWritePost', {
group = jupytext_group,
pattern = '*.py',
callback = function()
local ipynb_file = vim.fn.expand('%:r') .. '.ipynb'
if vim.fn.filereadable(ipynb_file) == 1 then
vim.cmd('silent! Jupytext --sync')
end
end,
})
vim.api.nvim_create_autocmd('BufWritePost', {
group = jupytext_group,
pattern = '*.ipynb',
callback = function()
local py_file = vim.fn.expand('%:r') .. '.py'
if vim.fn.filereadable(py_file) == 1 then
vim.cmd('silent! Jupytext --sync')
end
end,
})
vim.api.nvim_create_autocmd({ 'BufReadPost', 'BufNewFile' }, {
group = jupytext_group,
pattern = '*.ipynb',
callback = function()
local py_file = vim.fn.expand('%:r') .. '.py'
if vim.fn.filereadable(py_file) == 0 then
vim.cmd('silent! Jupytext --to py:percent')
end
if vim.fn.filereadable(py_file) == 1 then
vim.cmd('silent! edit ' .. vim.fn.fnameescape(py_file))
end
end,
})
end,
}

74
lua/custom/plugins/linting.lua Executable file
View file

@ -0,0 +1,74 @@
return {
'mfussenegger/nvim-lint',
dependencies = { 'WhoIsSethDaniel/mason-tool-installer.nvim' },
event = { 'BufReadPre', 'BufNewFile' },
opts = {
linters_by_ft = {
python = { 'ruff', 'mypy' },
go = { 'golangcilint' },
yaml = { 'yamllint' },
markdown = { 'markdownlint' },
sh = { 'shellcheck' },
lua = { 'luacheck' },
sql = { 'sqlfluff' },
},
mason_to_lint = {
golangcilint = { 'golangci-lint' },
},
},
config = function(_, opts)
local lint = require('lint')
lint.linters_by_ft = opts.linters_by_ft
-- Flatten linters and map to Mason package names
local all_linters = {}
for _, ft_linters in pairs(opts.linters_by_ft) do
for _, l in ipairs(ft_linters) do
local tool = opts.mason_to_lint[l] or { l }
-- Handle both table and string values
if type(tool) == 'table' then
for _, t in ipairs(tool) do
if t ~= '' then
table.insert(all_linters, t)
end
end
elseif tool ~= '' then
table.insert(all_linters, tool)
end
end
end
-- Deduplicate tools
local tools_set = {}
for _, t in ipairs(all_linters) do
tools_set[t] = true
end
local tools = vim.tbl_keys(tools_set)
print('Ensuring installation of linters: ' .. table.concat(tools, ', '))
-- Setup mason-tool-installer safely
require('mason-tool-installer').setup({
ensure_installed = tools,
auto_update = false,
run_on_start = true,
start_delay = 3000,
})
-- Autocommand group for linting
local augroup = vim.api.nvim_create_augroup('LintAutogroup', { clear = true })
vim.api.nvim_create_autocmd({ 'BufEnter', 'BufWritePost', 'InsertLeave' }, {
group = augroup,
callback = function()
local ft = vim.bo.filetype
local available = lint.linters_by_ft[ft]
if available and #available > 0 then
local ok, err = pcall(lint.try_lint)
if not ok then
vim.notify('[nvim-lint] Error running linter: ' .. err, vim.log.levels.ERROR)
end
end
end,
})
end,
}

552
lua/custom/plugins/lsp-config.lua Executable file
View file

@ -0,0 +1,552 @@
return {
'neovim/nvim-lspconfig',
event = { 'BufReadPre', 'BufNewFile' },
dependencies = {
-- Mason core
{ 'williamboman/mason.nvim', build = ':MasonUpdate', cmd = 'Mason', config = true },
'williamboman/mason-lspconfig.nvim',
'WhoIsSethDaniel/mason-tool-installer.nvim',
-- Lua dev
{ 'folke/neodev.nvim', ft = 'lua', config = true },
-- LSP UI & UX
{ 'j-hui/fidget.nvim', opts = {}, event = 'LspAttach' },
{ 'ray-x/lsp_signature.nvim', event = 'LspAttach' },
-- Treesitter
{
'nvim-treesitter/nvim-treesitter',
build = ':TSUpdate',
event = 'BufReadPost',
opts = {
highlight = { enable = true },
indent = { enable = true },
ensure_installed = {
'bash',
'c',
'cpp',
'go',
'html',
'julia',
'lua',
'markdown',
'python',
'rust',
'sql',
'vim',
'vimdoc',
'yaml',
'zig',
},
},
config = true,
},
{ 'nvim-treesitter/nvim-treesitter-textobjects', event = 'BufReadPost' },
-- Python venv selector
{
'linux-cultist/venv-selector.nvim',
ft = 'python',
opts = { auto_activate = true },
config = true,
},
-- JSON Schema support
{ 'b0o/schemastore.nvim', ft = { 'json', 'yaml' } },
},
config = function()
require('neodev').setup()
-- Enhanced capabilities for LSP servers
local capabilities = vim.lsp.protocol.make_client_capabilities()
local has_cmp, cmp_nvim_lsp = pcall(require, 'cmp_nvim_lsp')
if has_cmp then
capabilities = cmp_nvim_lsp.default_capabilities(capabilities)
end
capabilities.offsetEncoding = { 'utf-8' }
-- Disable dynamicRegistration to silence yamlls warning
capabilities.workspace = capabilities.workspace or {}
capabilities.workspace.didChangeConfiguration = capabilities.workspace.didChangeConfiguration or {}
capabilities.workspace.didChangeConfiguration.dynamicRegistration = false
local function path_exists(p)
return p and p ~= '' and vim.uv.fs_stat(p) ~= nil
end
local function mason_bin(name)
local p = vim.fs.joinpath(vim.fn.stdpath('data'), 'mason', 'bin', name)
if path_exists(p) then
return p
end
return name
end
local function julia_bin()
local home = vim.env.HOME or ''
local candidates = {
vim.fn.exepath('julia'),
vim.fs.joinpath(home, '.juliaup', 'bin', 'julia'),
'/opt/homebrew/bin/julia',
'/usr/local/bin/julia',
}
for _, p in ipairs(candidates) do
if path_exists(p) then
return p
end
end
return 'julia'
end
-- Servers that should provide formatting
local format_enabled_servers = {
bashls = true,
clangd = true,
gopls = true,
html = true,
htmx = true,
jsonls = true,
lua_ls = true,
marksman = true,
pyright = true,
ruff = true,
rust_analyzer = true,
taplo = true,
texlab = true,
yamlls = true,
zls = true,
}
-- Default on_attach function
local on_attach = function(client, bufnr)
-- Enable formatting only for supported servers
if not format_enabled_servers[client.name] then
client.server_capabilities.documentFormattingProvider = false
client.server_capabilities.documentRangeFormattingProvider = false
end
vim.bo[bufnr].omnifunc = 'v:lua.vim.lsp.omnifunc'
-- LSP signature help
require('lsp_signature').on_attach({
hint_enable = false,
handler_opts = { border = 'rounded' },
}, bufnr)
-- Keymap helper
local function map(keys, func, desc, modes)
modes = modes or 'n'
vim.keymap.set(modes, keys, func, {
buffer = bufnr,
desc = desc and 'LSP: ' .. desc or nil,
})
end
-- Lazy-load Telescope for LSP
local function telescope_builtin(name)
return function(...)
require('lazy').load({ plugins = { 'telescope.nvim' } })
return require('telescope.builtin')[name](...)
end
end
-- Navigation
map('gd', telescope_builtin('lsp_definitions'), '[G]oto [D]efinition')
map('gD', vim.lsp.buf.declaration, '[G]oto [D]eclaration')
map('gr', telescope_builtin('lsp_references'), '[G]oto [R]eferences')
map('gI', telescope_builtin('lsp_implementations'), '[G]oto [I]mplementation')
map('<leader>lT', telescope_builtin('lsp_type_definitions'), '[T]ype Definition')
map('<leader>ls', telescope_builtin('lsp_document_symbols'), '[D]ocument [S]ymbols')
map('<leader>lS', telescope_builtin('lsp_dynamic_workspace_symbols'), '[W]orkspace [S]ymbols')
-- Diagnostics
map('<leader>ld', vim.diagnostic.open_float, 'Show line [E]rrors')
map('[d', vim.diagnostic.get_prev, 'Previous Diagnostic')
map(']d', vim.diagnostic.get_next, 'Next Diagnostic')
-- Code Actions & Refactoring
map('<leader>lr', vim.lsp.buf.rename, 'Rename')
map('<leader>la', vim.lsp.buf.code_action, 'Code Action', { 'n', 'v' })
-- Documentation
map('K', vim.lsp.buf.hover, 'Hover Documentation')
map('<C-k>', vim.lsp.buf.signature_help, 'Signature Documentation')
-- Document highlight
if client.server_capabilities.documentHighlightProvider then
local highlight_group = vim.api.nvim_create_augroup('lsp_document_highlight', { clear = true })
local visual_bg = vim.fn.synIDattr(vim.fn.hlID('Visual'), 'bg') or '#3e4452'
vim.api.nvim_set_hl(0, 'LspReferenceText', { bg = visual_bg })
vim.api.nvim_set_hl(0, 'LspReferenceRead', { bg = visual_bg })
vim.api.nvim_set_hl(0, 'LspReferenceWrite', { bg = visual_bg })
vim.o.updatetime = math.max(vim.o.updatetime, 500)
local function toggle_lsp_highlight(enable)
if enable then
vim.api.nvim_create_autocmd('CursorHold', {
group = highlight_group,
buffer = bufnr,
callback = function()
if client and client.server_capabilities.documentHighlightProvider then
vim.lsp.buf.document_highlight()
end
end,
})
vim.api.nvim_create_autocmd('CursorMoved', {
group = highlight_group,
buffer = bufnr,
callback = vim.lsp.buf.clear_references,
})
else
vim.api.nvim_clear_autocmds({ group = highlight_group, buffer = bufnr })
vim.lsp.buf.clear_references()
end
end
vim.api.nvim_buf_create_user_command(bufnr, 'LspToggleHighlight', function()
local enabled = vim.b.lsp_highlight_enabled or false
toggle_lsp_highlight(not enabled)
vim.b.lsp_highlight_enabled = not enabled
print('LSP document highlights ' .. (enabled and 'disabled' or 'enabled'))
end, {})
toggle_lsp_highlight(true)
end
end
-- Default LSP configuration
local default_config = {
capabilities = capabilities,
on_attach = on_attach,
autostart = true,
}
local julia_cmd = julia_bin()
local julia_ls_project = vim.fn.expand('~/.julia/environments/nvim-lsp')
-- Server-specific configurations
local servers = {
bashls = {
filetypes = { 'sh', 'bash', 'zsh' },
},
html = {
filetypes = { 'html', 'htmldjango' },
init_options = {
configurationSection = { 'html', 'css', 'javascript' },
embeddedLanguages = {
css = true,
javascript = true,
},
},
},
htmx = {
cmd = { 'htmx-lsp' },
filetypes = { 'html', 'htmx' },
},
gopls = {
settings = {
gopls = {
gofumpt = true,
staticcheck = true,
completeUnimported = true,
usePlaceholders = true,
analyses = { unusedparams = true },
},
},
},
clangd = {
cmd = {
'clangd',
'--background-index',
'--clang-tidy',
'--header-insertion=iwyu',
'--completion-style=detailed',
'--header-insertion-decorators',
'--query-driver=/usr/bin/clang,/usr/bin/clang++',
'--enable-config',
},
settings = {
formatting = true,
inlayHints = {
designators = true,
enabled = true,
parameterNames = true,
deducedTypes = true,
},
},
filetypes = { 'c', 'cpp', 'objc', 'objcpp', 'h', 'hpp', 'hxx' },
},
marksman = {
filetypes = { 'markdown' },
settings = {
marksman = {
extensions = { 'mdx' },
},
},
},
jsonls = {
cmd = { 'vscode-json-language-server', '--stdio' },
settings = {
json = {
validate = { enable = true },
},
},
},
julials = {
filetypes = { 'julia' },
cmd = {
julia_cmd,
'--project=' .. julia_ls_project,
'--startup-file=no',
'--history-file=no',
'-e',
[[
using Logging
using LanguageServer
using SymbolServer
global_logger(ConsoleLogger(stderr, Logging.Warn))
function project_path()
try
return LanguageServer.find_project_path(pwd())
catch
return pwd()
end
end
depot_path = get(ENV, "JULIA_DEPOT_PATH", "")
server = LanguageServer.LanguageServerInstance(
stdin,
stdout,
something(project_path(), pwd()),
depot_path,
)
server.runlinter = true
run(server)
]],
},
settings = {
julia = {
lint = {
run = true,
},
},
},
on_attach = function(client, bufnr)
on_attach(client, bufnr)
-- Julia must never format via LSP
client.server_capabilities.documentFormattingProvider = false
client.server_capabilities.documentRangeFormattingProvider = false
end,
},
pyright = {
settings = {
python = {
analysis = {
autoSearchPaths = true,
diagnosticMode = 'workspace',
useLibraryCodeForTypes = true,
typeCheckingMode = 'none',
reportGeneralTypeIssues = false,
},
},
},
},
ruff = {
filetypes = { 'python' },
on_init = function()
vim.api.nvim_create_autocmd('LspAttach', {
group = vim.api.nvim_create_augroup('lsp_attach_disable_ruff_hover', { clear = true }),
callback = function(args)
local client = vim.lsp.get_client_by_id(args.data.client_id)
if client and client.name == 'ruff' then
-- Disable Ruff hover
client.server_capabilities.hoverProvider = false
end
end,
desc = 'LSP: Disable hover capability from Ruff',
})
end,
},
rust_analyzer = {
settings = {
['rust-analyzer'] = {
imports = { granularity = { group = 'module' }, prefix = 'self' },
cargo = { buildScripts = { enable = true } },
procMacro = { enable = true },
checkOnSave = { command = 'clippy' },
},
},
},
taplo = {
filetypes = { 'toml' },
},
yamlls = {
settings = {
yaml = {
schemaStore = { enable = true },
validate = true,
},
},
},
texlab = {
filetypes = { 'tex', 'plaintex', 'bib', 'cls', 'sty' },
settings = {
texlab = {
build = {
onSave = false,
},
diagnostics = {
ignoredPatterns = {
'^Overfull \\\\hbox',
'^Underfull \\\\hbox',
'^Package.*Warning',
},
},
auxDirectory = 'output',
},
},
},
lua_ls = {
cmd = { mason_bin('lua-language-server') },
settings = {
Lua = {
workspace = { checkThirdParty = false },
telemetry = { enable = false },
diagnostics = { globals = { 'vim' } },
},
},
},
sqls = {
filetypes = { 'sql', 'mysql', 'plsql', 'postgresql' },
settings = {
sql = {
connections = {
{
driver = 'sqlite3',
dataSourceName = 'file::memory:?cache=shared',
},
},
},
},
on_init = function(client)
local root_dir = client.config.root_dir or vim.fn.getcwd()
local db_files = vim.fn.globpath(root_dir, '*.db', false, true)
vim.list_extend(db_files, vim.fn.globpath(root_dir, '*.sqlite', false, true))
if #db_files > 0 then
local connections = {}
for _, path in ipairs(db_files) do
table.insert(connections, {
driver = 'sqlite3',
dataSourceName = vim.fn.fnamemodify(path, ':p'),
})
end
client.config.settings.sql.connections = connections
client.notify('workspace/didChangeConfiguration', { settings = client.config.settings })
end
end,
},
zls = {
filetypes = { 'zig' },
},
}
-- Use Mason to ensure servers are installed
local ensure_installed = vim.tbl_keys(servers)
ensure_installed = vim.tbl_filter(function(name)
return name ~= 'julials'
end, ensure_installed)
require('mason-lspconfig').setup({
ensure_installed = ensure_installed,
automatic_enable = false,
})
local function get_lspconfig_defaults(server_name)
local ok, cfg = pcall(require, 'lspconfig.configs.' .. server_name)
if ok and cfg and cfg.default_config then
local defaults = vim.deepcopy(cfg.default_config)
if type(defaults.root_dir) == 'function' then
local orig_root_dir = defaults.root_dir
defaults.root_dir = function(bufnr, on_dir)
local fname = bufnr
if type(bufnr) == 'number' then
fname = vim.api.nvim_buf_get_name(bufnr)
if fname == '' or type(fname) ~= 'string' or fname:match('^%w+://') then
fname = vim.fn.getcwd()
end
end
local root = orig_root_dir(fname)
if type(on_dir) == 'function' then
on_dir(root)
return
end
return root
end
end
return defaults
end
return {}
end
-- Setup and enable LSP servers
for server_name, config in pairs(servers) do
if config then
local lspconfig_defaults = get_lspconfig_defaults(server_name)
-- Merge default config with server-specific config
local merged_config = vim.tbl_deep_extend('force', lspconfig_defaults, default_config, config)
-- Configure and enable the server
vim.lsp.config(server_name, merged_config)
vim.lsp.enable(server_name)
end
end
-- Diagnostics configuration
vim.diagnostic.config({
underline = true,
severity_sort = true,
signs = {
text = {
[vim.diagnostic.severity.ERROR] = 'E',
[vim.diagnostic.severity.WARN] = 'W',
[vim.diagnostic.severity.HINT] = 'H',
[vim.diagnostic.severity.INFO] = 'I',
},
linehl = {
[vim.diagnostic.severity.ERROR] = 'ErrorMsg',
},
numhl = {
[vim.diagnostic.severity.WARN] = 'WarningMsg',
},
},
virtual_text = { spacing = 2, prefix = '' },
float = { source = 'if_many', border = 'rounded' },
})
end,
}

36
lua/custom/plugins/lualine.lua Executable file
View file

@ -0,0 +1,36 @@
return {
'nvim-lualine/lualine.nvim',
dependencies = { 'nvim-tree/nvim-web-devicons', 'tpope/vim-fugitive' },
config = function()
require('lualine').setup({
options = {
theme = 'auto',
icons_enabled = true,
component_separators = '|',
section_separators = '',
},
sections = {
lualine_a = {
{
'buffers',
show_modified_status = true,
symbols = { modified = '', alternate_file = '#', directory = '' },
},
},
lualine_b = {
{ 'mode', icons_enabled = true },
},
lualine_c = {
'branch',
{ 'diff', colored = false, symbols = { added = '', modified = '', removed = '' } },
},
lualine_x = {
'encoding',
{ 'fileformat', symbols = { unix = '', mac = '', dos = '' } },
'filetype',
},
},
extensions = { 'fugitive', 'nvim-tree' },
})
end,
}

8
lua/custom/plugins/marks.lua Executable file
View file

@ -0,0 +1,8 @@
return {
'chentoast/marks.nvim',
opts = {
default_mappings = true,
default_view = 'vertical',
},
}

8
lua/custom/plugins/monokai.lua Executable file
View file

@ -0,0 +1,8 @@
return {
'tanvirtin/monokai.nvim',
priority = 1000,
config = function()
end,
}

36
lua/custom/plugins/neogen.lua Executable file
View file

@ -0,0 +1,36 @@
return {
'danymat/neogen',
dependencies = {
'nvim-treesitter/nvim-treesitter',
'L3MON4D3/LuaSnip',
},
keys = {
{
'<leader>nf',
function()
require('neogen').generate({ type = 'func' })
end,
desc = 'Generate function documentation',
},
{
'<leader>nt',
function()
require('neogen').generate({ type = 'type' })
end,
desc = 'Generate type documentation',
},
},
config = function()
require('neogen').setup({
enabled = true,
snippet_engine = 'luasnip', -- Using LuaSnip as the snippet engine
})
end,
cond = function()
-- Only load if Treesitter is installed and available
return vim.fn.exists(':TSInstall') == 2
end,
-- Uncomment next line if you want to follow only stable versions
-- version = "*"
}

View file

@ -0,0 +1,137 @@
return {
{
'nvim-neotest/neotest',
dependencies = {
'nvim-lua/plenary.nvim',
'nvim-neotest/nvim-nio',
'nvim-treesitter/nvim-treesitter',
'nvim-neotest/neotest-python',
'alfaix/neotest-gtest',
'andythigpen/nvim-coverage',
},
keys = {
{
'<leader>tn',
function()
local neotest = require('neotest')
neotest.summary.open({ enter = false })
neotest.run.run()
end,
desc = 'Test: Run nearest',
},
{
'<leader>tf',
function()
local neotest = require('neotest')
neotest.summary.open({ enter = false })
neotest.run.run(vim.fn.expand('%'))
end,
desc = 'Test: Run file',
},
{
'<leader>ta',
function()
local neotest = require('neotest')
neotest.summary.open({ enter = false })
neotest.run.run(vim.fn.getcwd())
end,
desc = 'Test: Run all (cwd)',
},
{
'<leader>td',
function()
local neotest = require('neotest')
neotest.summary.open({ enter = false })
neotest.run.run({ strategy = 'dap' })
end,
desc = 'Test: Debug nearest',
},
{
'<leader>tx',
function()
require('neotest').run.stop()
end,
desc = 'Test: Stop',
},
{
'<leader>ts',
function()
require('neotest').summary.toggle()
end,
desc = 'Test: Toggle summary',
},
{
'<leader>to',
function()
require('neotest').output.open({ enter = true, auto_close = false })
end,
desc = 'Test: Show output',
},
{
'<leader>tw',
function()
require('neotest').watch.toggle(vim.fn.expand('%'))
end,
desc = 'Test: Watch file',
},
{
']t',
function()
require('neotest').jump.next({ status = 'failed' })
end,
desc = 'Test: Next failed',
},
{
'[t',
function()
require('neotest').jump.prev({ status = 'failed' })
end,
desc = 'Test: Prev failed',
},
{
'<leader>tC',
function()
local ok, coverage = pcall(require, 'coverage')
if ok then
coverage.toggle()
end
end,
desc = 'Test: Toggle coverage',
},
{
'<leader>tL',
function()
local ok, coverage = pcall(require, 'coverage')
if ok then
coverage.load(true)
end
end,
desc = 'Test: Load coverage',
},
},
config = function()
local neotest = require('neotest')
neotest.setup({
adapters = {
require('neotest-python')({
runner = 'pytest',
dap = { justMyCode = false },
}),
require('neotest-gtest').setup({
debug_adapter = 'codelldb',
}),
},
output = { open_on_run = false },
summary = { open = 'botright vsplit | vertical resize 60' },
})
local ok_cov, coverage = pcall(require, 'coverage')
if ok_cov then
coverage.setup({
auto_reload = true,
})
end
end,
},
}

View file

@ -0,0 +1,50 @@
return {
'rcarriga/nvim-notify',
opts = {
timeout = 5000,
stages = 'static',
},
config = function(_, opts)
local notify = require('notify')
notify.setup(opts)
-- Override vim.notify to filter out noisy LSP messages
local original_notify = vim.notify
vim.notify = function(msg, level, notify_opts)
-- Suppress Node.js warnings
if type(msg) == 'string' and msg:match('ExperimentalWarning: SQLite') then
return
end
if type(msg) == 'string' and msg:match('DeprecationWarning.*punycode') then
return
end
-- Suppress copilot errors (harmless race conditions)
if type(msg) == 'string' and msg:match('Cannot find request.*whilst attempting to cancel') then
return
end
if type(msg) == 'string' and msg:match('AbortError: The operation was aborted') then
return
end
if type(msg) == 'string' and msg:match('rate limit exceeded') then
return
end
if type(msg) == 'string' and msg:match('Rate limited by server') then
return
end
-- Suppress bashls parsing/formatting errors
if type(msg) == 'string' and msg:match('Error while parsing file://') then
return
end
if type(msg) == 'string' and msg:match('Error while formatting.*Shfmt') then
return
end
original_notify(msg, level, notify_opts)
end
-- Set as default notifier
vim.notify = notify
end,
}

74
lua/custom/plugins/oil.lua Executable file
View file

@ -0,0 +1,74 @@
return {
'stevearc/oil.nvim',
dependencies = {
'nvim-tree/nvim-web-devicons', -- optional, for file icons
},
config = function()
local oil = require('oil')
oil.setup({
columns = {
'icon',
-- 'permissions',
},
keymaps = {
['C-h'] = false,
['M-h'] = 'actions.select_split',
},
view_options = {
show_hidden = true,
},
float = {
padding = 2,
max_width = 80,
max_height = 30,
border = 'rounded',
win_options = {
winblend = 0,
},
relative = 'editor',
},
})
-- Monokai-like highlights
vim.api.nvim_set_hl(0, 'OilDir', { fg = '#A6E22E' })
vim.api.nvim_set_hl(0, 'OilFile', { fg = '#D3D0C8' })
vim.api.nvim_set_hl(0, 'OilHiddenFile', { fg = '#75715E' })
vim.api.nvim_set_hl(0, 'OilProgress', { fg = '#66D9EF' })
vim.api.nvim_set_hl(0, 'OilSymlink', { fg = '#F92672' })
-- Oil keymaps
vim.keymap.set('n', '<leader>e', '<CMD>Oil<CR>', { noremap = true, silent = true, desc = 'Open parent directory' })
vim.keymap.set('n', '<leader>E', function()
oil.toggle_float()
end, { noremap = true, silent = true, desc = 'Toggle oil floating window' })
-- Add selected file in oil.nvim to Harpoon
-- same keymapping as if in a buffer
vim.keymap.set('n', '<leader>a', function()
local ok_harpoon, harpoon = pcall(require, 'harpoon')
if not ok_harpoon then
vim.notify('Harpoon not found', vim.log.levels.WARN)
return
end
local entry = oil.get_cursor_entry()
if not entry or not entry.name then
vim.notify('No valid entry selected in Oil', vim.log.levels.INFO)
return
end
local full_path = oil.get_current_dir() .. entry.name
local stat = vim.loop.fs_stat(full_path)
if not stat or stat.type ~= 'file' then
vim.notify('Selected entry is not a file: ' .. full_path, vim.log.levels.INFO)
return
end
harpoon:list():add({
value = entry.name,
context = { filename = entry.name, cwd = oil.get_current_dir() or 'global' },
})
end, { desc = 'Add selected file in oil.nvim to Harpoon' })
end,
}

View file

@ -0,0 +1,12 @@
return {
{
'ThePrimeagen/refactoring.nvim',
event = 'VeryLazy',
dependencies = {
'nvim-lua/plenary.nvim',
'nvim-treesitter/nvim-treesitter',
},
lazy = true,
opts = {},
},
}

View file

@ -0,0 +1,10 @@
return {
'MeanderingProgrammer/render-markdown.nvim',
ft = { 'markdown' },
dependencies = {
'nvim-tree/nvim-web-devicons',
},
opts = {
-- Put any overrides here only if you need them.
},
}

View file

@ -0,0 +1,5 @@
return {
'b0o/schemastore.nvim',
ft = { 'josn', 'jsonc', 'json5', 'yaml', 'toml' },
event = 'VeryLazy',
}

40
lua/custom/plugins/slime.lua Executable file
View file

@ -0,0 +1,40 @@
return {
'jpalardy/vim-slime',
ft = { 'python' },
keys = {
{ '<leader>RC', '<cmd>SlimeConfig<cr>', desc = 'Slime Config' },
{
'<leader>RS',
function()
if require('custom.user.ipython_utils').is_ipython_open() then
if vim.fn.mode() == 'v' then
-- Visual mode mapping
vim.cmd("<cmd><C-u>'<,'>SlimeSend<CR>")
else
-- Normal mode mapping: Execute the <Plug>SlimeSendCell and move to the next cell delimiter
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes('<Plug>SlimeSendCell', true, true, true), 'm', true)
vim.cmd('normal! /^# %%\\<CR>')
end
else
vim.notify('No IPython REPL found. Open an IPython terminal first.', vim.log.levels.WARN)
end
end,
mode = { 'n', 'v' },
},
},
init = function()
vim.g.slime_target = 'neovim'
vim.g.slime_no_mappings = true
end,
config = function()
-- Slime configuration
vim.g.slime_cell_delimiter = '# %%'
vim.g.slime_bracketed_paste = 1
vim.g.slime_paste_file = os.getenv('HOME') .. '/.slime_paste'
vim.g.slime_input_pid = false
vim.g.slime_suggest_default = true
vim.g.slime_menu_config = false
vim.g.slime_neovim_ignore_unlisted = false
vim.g.slime_python_ipython = 0
end,
}

42
lua/custom/plugins/snippets.lua Executable file
View file

@ -0,0 +1,42 @@
return {
{
'L3MON4D3/LuaSnip',
version = 'v2.*', -- Follows the latest major release version 2
build = 'make install_jsregexp', -- Optional: install JavaScript-based regular expressions
dependencies = { 'rafamadriz/friendly-snippets' },
config = function()
local luasnip = require('luasnip')
-- Extend filetypes with specific snippets
luasnip.filetype_extend('javascript', { 'jsdoc' })
luasnip.filetype_extend('python', { 'google' })
-- Key mappings for LuaSnip
vim.keymap.set({ 'i' }, '<C-s>e', function()
if luasnip.expand_or_jumpable() then
luasnip.expand()
end
end, { silent = true, desc = 'Expand snippet' })
vim.keymap.set({ 'i', 's' }, '<C-s>;', function()
if luasnip.jumpable(1) then
luasnip.jump(1)
end
end, { silent = true, desc = 'Jump forward in snippet' })
vim.keymap.set({ 'i', 's' }, '<C-s>,', function()
if luasnip.jumpable(-1) then
luasnip.jump(-1)
end
end, { silent = true, desc = 'Jump backward in snippet' })
vim.keymap.set({ 'i', 's' }, '<C-s>', function()
if luasnip.choice_active() then
luasnip.change_choice(1)
end
end, { silent = true, desc = 'Cycle through snippet choices' })
end,
},
}

View file

@ -0,0 +1,7 @@
return {
'shaunsingh/solarized.nvim',
event = 'VeryLazy',
config = function()
vim.g.solarized_variant = 'light'
end,
}

View file

@ -0,0 +1,5 @@
return {
'tpope/vim-surround',
event = { 'BufRead', 'BufNewFile' },
config = function() end,
}

View file

@ -0,0 +1,44 @@
return {
-- "debugloop/telescope-undo.nvim",
-- dependencies = { -- note how they're inverted to above example
-- {
-- "nvim-telescope/telescope.nvim",
-- dependencies = { "nvim-lua/plenary.nvim" },
-- },
-- },
-- keys = {
-- { -- lazy style key map
-- "<leader>u", "<cmd>Telescope undo<cr>", desc = "undo history",
-- },
-- },
-- opts = {
-- extensions = {
-- undo = {
-- mapping = {
-- i = {
-- ["<cr>"] = require("telescope-undo.actions").yank_additions,
-- ["<c-d>"] = require("telescope-undo.actions").yank_deletions,
-- ["<c-r>"] = require("telescope-undo.actions").restore,
-- },
-- n = {
-- ["y"] = require("telescope-undo.actions").yank_additions,
-- ["Y"] = require("telescope-undo.actions").yank_deletions,
-- ["u"] = require("telescope-undo.actions").restore,
-- },
-- },
-- side_by_side = true,
-- layout_strategy = "vertical",
-- layout_config = {
-- preview_height = 0.8,
-- },
-- },
-- },
-- },
-- config = function(_, opts)
-- -- Calling telescope's setup from multiple specs does not hurt, it will happily merge the
-- -- configs for us. We won't use data, as everything is in it's own namespace (telescope
-- -- defaults, as well as each extension).
-- require("telescope").setup(opts)
-- require("telescope").load_extension("undo")
-- end,
}

View file

@ -0,0 +1,96 @@
return {
-- Fuzzy Finder (files, LSP, etc.)
'nvim-telescope/telescope.nvim',
cmd = 'Telescope',
version = '*',
dependencies = {
'nvim-lua/plenary.nvim',
'debugloop/telescope-undo.nvim', -- Undo history extension
{
'nvim-telescope/telescope-fzf-native.nvim',
build = 'make',
config = function()
require('telescope').setup({
extensions = {
fzf = {},
},
})
require('telescope').load_extension('fzf')
end,
cond = function()
return vim.fn.executable('make') == 1
end,
},
'nvim-tree/nvim-web-devicons', -- Optional: Icons for UI
'mbbill/undotree', -- Undotree dependency
-- 'b0o/schemastore.nvim', -- YAML schema support
},
config = function()
local telescope = require('telescope')
-- Configure Telescope
telescope.setup({
defaults = {
-- prompt_prefix = '🔍 ',
sorting_strategy = 'descending',
layout_strategy = 'flex',
mappings = {
i = {
['<C-u>'] = false, -- Disable Ctrl+u clearing input
['<C-d>'] = false, -- Disable Ctrl+d clearing input
},
},
-- Attach the global mapping for centering the cursor on selection
attach_mappings = function(prompt_bufnr, _)
local actions = require('telescope.actions')
-- When selecting a result, center it in the middle of the screen
actions.select_default:replace(function()
local line = actions.state.get_selected_entry().lnum
vim.api.nvim_win_set_cursor(0, { line, 0 })
vim.cmd('normal! zz') -- This centers the line in the middle of the screen
actions.close(prompt_bufnr) -- Close the Telescope window
end)
return true
end,
},
extensions = {
undo = {
use_delta = true, -- Use delta for better diff visualization
},
},
})
-- Load the undo extension for Telescope
telescope.load_extension('undo')
-- Load yaml schemas for Telescope
-- telescope.load_extension('yaml_schema')
-- Function to find git root directory
local function find_git_root()
local current_file = vim.api.nvim_buf_get_name(0)
local current_dir = current_file ~= '' and vim.fn.fnamemodify(current_file, ':h') or vim.fn.getcwd()
local git_root =
vim.fn.systemlist('git -C ' .. vim.fn.escape(current_dir, ' ') .. ' rev-parse --show-toplevel')[1]
if vim.v.shell_error ~= 0 then
print('Not a git repository, searching in current directory.')
return vim.fn.getcwd()
end
return git_root
end
-- Function for live_grep within the Git root
local function live_grep_git_root()
local git_root = find_git_root()
if git_root then
require('telescope.builtin').live_grep({ search_dirs = { git_root } })
end
end
-- Command to trigger live_grep_git_root
vim.api.nvim_create_user_command('LiveGrepGitRoot', live_grep_git_root, { desc = 'Live grep in Git root' })
end,
}

11
lua/custom/plugins/terminal.lua Executable file
View file

@ -0,0 +1,11 @@
return {
{
'floaterminal',
dir = vim.fn.stdpath('config') .. '/lua/plugins',
config = function()
require('plugins.floaterminal').setup({
title = 'Terminal',
})
end,
},
}

View file

@ -0,0 +1,7 @@
-- Highlight todo, notes, etc in comments
return {
'folke/todo-comments.nvim',
event = 'VimEnter',
dependencies = { 'nvim-lua/plenary.nvim' },
opts = { signs = false },
}

View file

@ -0,0 +1,106 @@
return {
'nvim-treesitter/nvim-treesitter',
branch = 'master',
version = false, -- last release is too old and doesn't work on Windows
build = ':TSUpdate',
event = { 'VeryLazy' },
lazy = vim.fn.argc(-1) == 0, -- load treesitter early when opening a file from the cmdline
init = function(plugin)
-- PERF: add nvim-treesitter queries to the rtp and its custom query predicates early
require('lazy.core.loader').add_to_rtp(plugin)
require('nvim-treesitter.query_predicates')
end,
cmd = { 'TSUpdateSync', 'TSUpdate', 'TSInstall' },
keys = {
{ '<c-space>', desc = 'Increment Selection' },
{ '<bs>', desc = 'Decrement Selection', mode = 'x' },
},
opts_extend = { 'ensure_installed' },
---@type TSConfig
---@diagnostic disable-next-line: missing-fields
opts = {
highlight = { enable = true },
indent = { enable = true },
ensure_installed = {
'bash',
'c',
'html',
'javascript',
'jsdoc',
'json',
'jsonc',
'lua',
'luadoc',
'markdown',
'markdown_inline',
'python',
'query',
'toml',
'vim',
'vimdoc',
'yaml',
'sql',
'zig',
},
incremental_selection = {
enable = true,
keymaps = {
init_selection = 'gnn',
node_incremental = 'grn',
scope_incremental = 'grc',
node_decremental = 'grm',
},
},
textobjects = {
select = {
enable = true,
lookahead = true,
keymaps = {
['aa'] = '@parameter.outer',
['ia'] = '@parameter.inner',
['af'] = '@function.outer',
['if'] = '@function.inner',
['ac'] = '@class.outer',
['ic'] = '@class.inner',
},
},
move = {
enable = true,
set_jumps = true,
goto_next_start = {
[']m'] = '@function.outer',
[']]'] = '@class.outer',
},
goto_next_end = {
[']M'] = '@function.outer',
[']['] = '@class.outer',
},
goto_previous_start = {
['[m'] = '@function.outer',
['[['] = '@class.outer',
},
goto_previous_end = {
['[M'] = '@function.outer',
['[]'] = '@class.outer',
},
},
swap = {
enable = true,
swap_next = {
['<leader>i'] = '@parameter.inner',
},
swap_previous = {
['<leader>I'] = '@parameter.inner',
},
},
},
},
---@param opts TSConfig
config = function(_, opts)
-- Ensure no duplicates in the ensure_installed list
if type(opts.ensure_installed) == 'table' then
opts.ensure_installed = vim.tbl_deep_extend('force', {}, opts.ensure_installed)
end
require('nvim-treesitter.configs').setup(opts)
end,
}

39
lua/custom/plugins/trouble.lua Executable file
View file

@ -0,0 +1,39 @@
return {
'folke/trouble.nvim',
version = '*',
opts = {}, -- for default options, refer to the configuration section for custom setup.
cmd = 'Trouble',
event = 'LspAttach',
keys = {
{
'<leader>xx',
'<cmd>Trouble diagnostics toggle<cr>',
desc = 'Diagnostics (Trouble)',
},
{
'<leader>xX',
'<cmd>Trouble diagnostics toggle filter.buf=0<cr>',
desc = 'Buffer Diagnostics (Trouble)',
},
{
'<leader>xs',
'<cmd>Trouble symbols toggle focus=false<cr>',
desc = 'Symbols (Trouble)',
},
{
'<leader>xl',
'<cmd>Trouble lsp toggle focus=false win.position=right<cr>',
desc = 'LSP Definitions / references / ... (Trouble)',
},
{
'<leader>xL',
'<cmd>Trouble loclist toggle<cr>',
desc = 'Location List (Trouble)',
},
{
'<leader>xQ',
'<cmd>Trouble qflist toggle<cr>',
desc = 'Quickfix List (Trouble)',
},
},
}

View file

@ -0,0 +1,9 @@
return {
'mbbill/undotree',
config = function()
-- Set Undotree to open on the right side
vim.g.undotree_WindowLayout = 4
vim.keymap.set('n', '<leader>u', vim.cmd.UndotreeToggle, { desc = '[U]ndotree' })
end,
}

View file

@ -0,0 +1,29 @@
return {
'linux-cultist/venv-selector.nvim',
cmd = 'VenvSelect',
dependencies = {
'neovim/nvim-lspconfig',
'nvim-telescope/telescope.nvim',
-- Remove nvim-dap-python from here - it's defined separately
},
opts = {
settings = {
options = {
activate_venv_in_terminal = true,
notify_user_on_venv_activation = true,
debug = true,
},
search = {
pyenv = {
command = 'fd python$ -E "*lib*" -E "*init*" ${PYENV_ROOT}/versions/*.*.*/envs',
on_telescope_result_callback = function(filename)
return filename:gsub(os.getenv('HOME'), '~'):gsub('/bin/python', '')
end,
},
},
},
},
keys = {
{ ',v', '<cmd>VenvSelect<cr>', desc = 'Select Virtual Environment' },
},
}

187
lua/custom/plugins/vimtex.lua Executable file
View file

@ -0,0 +1,187 @@
return {
'lervag/vimtex',
ft = { 'tex', 'latex', 'cls', 'sty', 'bib' },
lazy = false,
init = function()
-- macOS PDF viewer - Skim is better than Zathura on macOS
vim.g.vimtex_view_method = 'skim'
vim.g.vimtex_view_skim_sync = 1
vim.g.vimtex_view_skim_activate = 1
vim.g.vimtex_view_skim_reading_bar = 0
vim.g.vimtex_view_skim_preserve_state = 1
-- Alternative: use system default PDF viewer
-- vim.g.vimtex_view_method = 'general'
-- vim.g.vimtex_view_general_viewer = 'open'
-- Compiler
vim.g.vimtex_compiler_method = 'latexmk'
vim.g.vimtex_compiler_latexmk_engines = {
_ = '-pdf -xelatex -synctex=1 -interaction=nonstopmode',
}
vim.g.vimtex_compiler_latexmk = {
build_dir = 'output',
aux_dir = 'output',
callback = 1,
continuous = 1,
executable = 'latexmk',
options = {
-- '-pdf',
'-verbose',
'-file-line-error',
-- '-synctex=1',
'-interaction=nonstopmode',
-- '-xelatex',
'-shell-escape',
'-outdir=output',
'-auxdir=output',
},
}
-- Disable problematic default mappings
vim.g.vimtex_mappings_disable = {
['n'] = { 'K' },
['x'] = { 'K' },
}
-- Quickfix
vim.g.vimtex_quickfix_method = vim.fn.executable('pplatex') == 1 and 'pplatex' or 'latexlog'
vim.g.vimtex_quickfix_mode = 2
vim.g.vimtex_quickfix_open_on_warning = 0
vim.g.vimtex_quickfix_ignore_filters = {
'Underfull \\hbox',
'Overfull \\hbox',
'LaTeX Warning: .+ float specifier changed to',
'LaTeX hooks Warning',
'Package hyperref Warning: Token not allowed in a PDF string',
'Package fontspec Warning',
'Package everypage Warning',
'Package microtype Warning',
'LaTeX Warning: Command \\. invalid in math mode',
'Package babel Warning',
'Package biblatex Warning',
}
-- Folding
vim.g.vimtex_fold_enabled = 1
vim.g.vimtex_fold_types = {
envs = { whitelist = { 'figure', 'table', 'equation', 'align' } },
sections = { parse_levels = 1 },
}
-- Syntax
vim.g.vimtex_syntax_enabled = 1
vim.g.vimtex_syntax_conceal = {
accents = 0,
ligatures = 0,
cites = 1,
fancy = 0,
spacing = 0,
greek = 1,
math_bounds = 0,
math_delimiters = 0,
math_fracs = 0,
math_super_sub = 1,
math_symbols = 1,
sections = 0,
}
end,
config = function()
-- Auto-create output dir
vim.api.nvim_create_autocmd({ 'BufNewFile', 'BufRead' }, {
pattern = { '*.tex', '*.latex' },
callback = function()
if vim.bo.filetype == 'tex' or vim.bo.filetype == 'latex' then
local output_dir = vim.fn.expand('%:p:h') .. '/output'
if vim.fn.isdirectory(output_dir) == 0 then
vim.fn.mkdir(output_dir, 'p')
end
end
end,
})
-- Toggle continuous compilation function
_G.vimtex_toggle_continuous = function()
if vim.g.vimtex_compiler_latexmk.continuous == 1 then
vim.g.vimtex_compiler_latexmk.continuous = 0
print('Continuous compilation OFF')
vim.cmd('VimtexStop')
else
vim.g.vimtex_compiler_latexmk.continuous = 1
print('Continuous compilation ON')
vim.cmd('VimtexCompile')
end
end
-- Function to close Skim for current PDF
local function close_skim()
local file_name = vim.fn.expand('%:t:r')
if file_name ~= '' then
local pdf_name = file_name .. '.pdf'
-- AppleScript to close Skim window for specific PDF
local script = string.format(
[[
tell application "System Events"
if (name of processes) contains "Skim" then
tell application "Skim"
set theWindows to every window whose name contains "%s"
repeat with theWindow in theWindows
close theWindow
end repeat
end tell
end if
end tell
]],
pdf_name
)
vim.fn.system({ 'osascript', '-e', script })
end
end
-- Auto-close Skim when LaTeX buffer is deleted or closed
vim.api.nvim_create_autocmd({ 'BufDelete', 'BufWipeout' }, {
pattern = { '*.tex', '*.latex' },
callback = function()
close_skim()
end,
})
-- Also close when Neovim exits
vim.api.nvim_create_autocmd('VimLeave', {
pattern = { '*.tex', '*.latex' },
callback = function()
close_skim()
end,
})
end,
-- Use VimTeX's standard keymaps - only add minimal custom ones
keys = {
-- Standard VimTeX mappings (these are the defaults, just making them explicit)
{ '<localleader>ll', '<cmd>VimtexCompile<cr>', desc = 'VimTeX: Compile', ft = { 'tex', 'latex' } },
{ '<localleader>lv', '<cmd>VimtexView<cr>', desc = 'VimTeX: View PDF', ft = { 'tex', 'latex' } },
{ '<localleader>ls', '<cmd>VimtexStop<cr>', desc = 'VimTeX: Stop', ft = { 'tex', 'latex' } },
{ '<localleader>lS', '<cmd>VimtexStopAll<cr>', desc = 'VimTeX: Stop All', ft = { 'tex', 'latex' } },
{ '<localleader>lc', '<cmd>VimtexClean<cr>', desc = 'VimTeX: Clean', ft = { 'tex', 'latex' } },
{ '<localleader>lC', '<cmd>VimtexClean!<cr>', desc = 'VimTeX: Clean All', ft = { 'tex', 'latex' } },
{ '<localleader>lq', '<cmd>VimtexErrors<cr>', desc = 'VimTeX: Errors', ft = { 'tex', 'latex' } },
{ '<localleader>lk', '<cmd>VimtexLog<cr>', desc = 'VimTeX: Log', ft = { 'tex', 'latex' } },
{ '<localleader>li', '<cmd>VimtexInfo<cr>', desc = 'VimTeX: Info', ft = { 'tex', 'latex' } },
{ '<localleader>lI', '<cmd>VimtexInfoFull<cr>', desc = 'VimTeX: Info Full', ft = { 'tex', 'latex' } },
{ '<localleader>lt', '<cmd>VimtexTocToggle<cr>', desc = 'VimTeX: TOC Toggle', ft = { 'tex', 'latex' } },
{ '<localleader>lT', '<cmd>VimtexTocOpen<cr>', desc = 'VimTeX: TOC Open', ft = { 'tex', 'latex' } },
{ '<localleader>lw', '<cmd>VimtexCountWords<cr>', desc = 'VimTeX: Count Words', ft = { 'tex', 'latex' } },
{ '<localleader>lW', '<cmd>VimtexCountLetters<cr>', desc = 'VimTeX: Count Letters', ft = { 'tex', 'latex' } },
{ '<localleader>lm', '<cmd>VimtexImapsList<cr>', desc = 'VimTeX: Imaps List', ft = { 'tex', 'latex' } },
-- Only one custom mapping for continuous compilation toggle
{
'<localleader>lR',
function()
_G.vimtex_toggle_continuous()
end,
desc = 'VimTeX: Toggle Continuous',
ft = { 'tex', 'latex' },
},
},
}

View file

@ -0,0 +1,6 @@
return {
'willothy/wezterm.nvim',
opts = {
create_commands = false
}
}

View file

@ -0,0 +1,62 @@
return {
'folke/which-key.nvim',
event = 'VimEnter', -- Sets the loading event to 'VimEnter'
icons = {
mappings = true,
keys = {
Up = '<Up> ',
Down = '<Down> ',
Left = '<Left> ',
Right = '<Right> ',
C = '<C-…> ',
M = '<M-…> ',
D = '<D-…> ',
S = '<S-…> ',
CR = '<CR> ',
Esc = '<Esc> ',
ScrollWheelDown = '<ScrollWheelDown> ',
ScrollWheelUp = '<ScrollWheelUp> ',
NL = '<NL> ',
BS = '<BS> ',
Space = '<Space> ',
Tab = '<Tab> ',
F1 = '<F1>',
F2 = '<F2>',
F3 = '<F3>',
F4 = '<F4>',
F5 = '<F5>',
F6 = '<F6>',
F7 = '<F7>',
F8 = '<F8>',
F9 = '<F9>',
F10 = '<F10>',
F11 = '<F11>',
F12 = '<F12>',
},
},
opts = {
preset = 'helix', -- I like helix because I can still see the text, but others: modernm, classic
spec = {
{ '<leader>a', group = 'Harpoon', mode = { 'n', 'x' } },
{ '<leader>b', group = '[B]uffer' },
{ '<leader>c', group = '[C]ode/C++', mode = { 'n', 'x' } },
{ '<leader>C', group = '[C]opilot', mode = {'n', 'x'} },
{ '<leader>d', group = '[D]ebug' },
{ '<leader>e', group = '[E]xplorer' },
{ '<leader>f', group = '[F]iles' },
{ '<leader>g', group = '[G]it' },
{ '<leader>h', group = 'Git [H]unk', mode = { 'n', 'v' } },
{ '<leader>j', group = '[J]ulia', mode = { 'n', 'x' } },
{ '<leader>l', group = '[L]SP' },
{ '<leader>p', group = '[P]aste', mode = { 'n', 'x' } },
{ '<leader>R', group = '[R]un/REPL', mode = { 'n', 'x' } },
{ '<leader>r', group = '[R]eplace' },
{ '<leader>s', group = '[S]earch' },
{ '<leader>t', group = '[T]est' },
{ '<leader>u', group = '[U]I' },
{ '<leader>w', group = '[W]orkspace' },
{ '<leader>x', group = 'Trouble' },
{ '<leader>z', group = '[Z]en' },
},
},
}

View file

@ -0,0 +1,20 @@
return {
'ThePrimeagen/git-worktree.nvim',
config = function()
require('git-worktree').setup()
require('telescope').load_extension('git_worktree')
vim.keymap.set(
'n',
'<leader>ga',
"<cmd>lua require('telescope').extensions.git_worktree.git_worktree()<CR>",
{ desc = 'Git Worktrees' }
)
vim.keymap.set(
'n',
'<leader>gn',
"<cmd>lua require('telescope').extensions.git_worktree.create_git_worktree()<CR>",
{ desc = 'New Git Worktree' }
)
end,
}

42
lua/custom/plugins/zen-mode.lua Executable file
View file

@ -0,0 +1,42 @@
return {
'folke/zen-mode.nvim',
command = 'ZenMode',
opts = {
window = {
backdrop = 0.95, -- Transparency level for the zen mode window
width = 0.80, -- 80% of the total editor width
height = 1, -- Full height
options = {
signcolumn = 'no', -- Hide signcolumn in zen mode
number = true, -- Disable line numbers
relativenumber = true, -- Disable relative numbers
},
},
plugins = {
wezterm = {
enabled = true,
font = '+2', -- Increase font size in WezTerm by 2
},
},
on_open = function()
-- Configure Neovim options when Zen Mode opens
vim.opt.ruler = false -- Hide ruler
vim.opt.showcmd = false -- Hide command feedback
vim.opt.laststatus = 0 -- Hide status line
end,
on_close = function()
-- Restore Neovim options when Zen Mode closes
vim.opt.ruler = true -- Show ruler
vim.opt.showcmd = true -- Show command feedback
vim.opt.laststatus = 2 -- Show status line
end,
},
keys = {
{
'<leader>zz',
'<cmd>ZenMode<CR>',
desc = 'Toggle Zen Mode',
silent = true,
},
},
}

View file

@ -0,0 +1,26 @@
local ls = require('luasnip')
local s = ls.snippet
local i = ls.insert_node
local t = ls.text_node
local fmt = require('luasnip.extras.fmt').fmt
ls.add_snippets('go', {
s('ee', {
t({ 'panic(' }),
i(1, 'err'),
t({ ')' }),
}),
s(
'ei',
fmt(
[[
if err != nil {{
panic({})
}}
]],
{ i(1, 'err') }
)
),
})

View file

@ -0,0 +1,20 @@
local ls = require 'luasnip'
local s = ls.snippet
local i = ls.insert_node
local t = ls.text_node
ls.add_snippets('lua', {
s('lr', {
t 'local ',
i(1, 'module'),
t ' = require("',
i(2, 'module'),
t '")',
}),
s('pr', {
t 'print(',
i(1, 'text'),
t ')',
}),
})

View file

@ -0,0 +1,51 @@
local ls = require('luasnip')
local s = ls.snippet
local i = ls.insert_node
local t = ls.text_node
local d = ls.dynamic_node
local sn = ls.snippet_node
-- Helper to parse function args and create insert nodes
local function generate_arg_docs()
local line = vim.api.nvim_get_current_line()
local args = line:match('def%s+[%w_]+%((.*)%)')
if not args then
return sn(nil, { t('Args:') })
end
local nodes = { t('Args:') }
local index = 1
for arg in args:gmatch('[^,%s]+') do
table.insert(nodes, t({ '', ' ' .. arg .. ': ' }))
table.insert(nodes, i(index))
index = index + 1
end
return sn(nil, nodes)
end
-- Add Python snippets
ls.add_snippets('python', {
s('log', {
t({ 'LOG.' }),
i(1, 'level'),
t({ '(' }),
i(2, 'message'),
t({ ')' }),
}),
s('#!', {
t({ '#!/usr/bin/env python' }),
}),
-- Docstring with Args (interactive) and Returns
s('doc', {
t({ '"""' }),
d(1, generate_arg_docs, {}),
t({ '', '', 'Returns:', ' ' }),
i(2, 'return_value_description'),
t({ '', '"""' }),
}),
})

2
lua/custom/user/init.lua Normal file
View file

@ -0,0 +1,2 @@
-- Load user-created modules
require('custom.user.ipython_utils')

View file

@ -0,0 +1,24 @@
local M = {}
-- Function to check if an IPython REPL is open in Neovim panes
function M.is_ipython_open()
for _, bufnr in ipairs(vim.api.nvim_list_bufs()) do
if vim.api.nvim_buf_is_loaded(bufnr) and vim.api.nvim_get_option_value('buftype', { buf = bufnr }) == 'terminal' then
if vim.b[bufnr].python_repl == true then
return true
end
-- Get first few lines to check if it's an IPython REPL
local lines = vim.api.nvim_buf_get_lines(bufnr, 0, 10, false)
for _, line in ipairs(lines) do
-- Specific checks for IPython
if line:match('IPython') or line:match('In %[%d+%]:') or line:match('In %[') then
return true
end
end
end
end
return false
end
return M

View file

@ -0,0 +1,76 @@
-- autoformat.lua
--
-- Use your language server to automatically format your code on save.
-- Adds additional commands as well to manage the behavior
return {
'neovim/nvim-lspconfig',
config = function()
-- Switch for controlling whether you want autoformatting.
-- Use :KickstartFormatToggle to toggle autoformatting on or off
local format_is_enabled = true
vim.api.nvim_create_user_command('KickstartFormatToggle', function()
format_is_enabled = not format_is_enabled
print('Setting autoformatting to: ' .. tostring(format_is_enabled))
end, {})
-- Create an augroup that is used for managing our formatting autocmds.
-- We need one augroup per client to make sure that multiple clients
-- can attach to the same buffer without interfering with each other.
local _augroups = {}
local get_augroup = function(client)
if not _augroups[client.id] then
local group_name = 'kickstart-lsp-format-' .. client.name
local id = vim.api.nvim_create_augroup(group_name, { clear = true })
_augroups[client.id] = id
end
return _augroups[client.id]
end
-- Whenever an LSP attaches to a buffer, we will run this function.
--
-- See `:help LspAttach` for more information about this autocmd event.
vim.api.nvim_create_autocmd('LspAttach', {
group = vim.api.nvim_create_augroup('kickstart-lsp-attach-format', { clear = true }),
-- This is where we attach the autoformatting for reasonable clients
callback = function(args)
local client_id = args.data.client_id
local client = vim.lsp.get_client_by_id(client_id)
local bufnr = args.buf
if not client then
return
end
-- Only attach to clients that support document formatting
if not client.server_capabilities.documentFormattingProvider then
return
end
-- Tsserver usually works poorly. Sorry you work with bad languages
-- You can remove this line if you know what you're doing :)
if client.name == 'tsserver' then
return
end
-- Create an autocmd that will run *before* we save the buffer.
-- Run the formatting command for the LSP that has just attached.
vim.api.nvim_create_autocmd('BufWritePre', {
group = get_augroup(client),
buffer = bufnr,
callback = function()
if not format_is_enabled then
return
end
vim.lsp.buf.format({
async = false,
filter = function(c)
return c.id == client.id
end,
})
end,
})
end,
})
end,
}

88
lua/kickstart/plugins/debug.lua Executable file
View file

@ -0,0 +1,88 @@
-- debug.lua
--
-- Shows how to use the DAP plugin to debug your code.
--
-- Primarily focused on configuring the debugger for Go, but can
-- be extended to other languages as well. That's why it's called
-- kickstart.nvim and not kitchen-sink.nvim ;)
return {
-- NOTE: Yes, you can install new plugins here!
'mfussenegger/nvim-dap',
-- NOTE: And you can specify dependencies as well
dependencies = {
-- Creates a beautiful debugger UI
'rcarriga/nvim-dap-ui',
-- Installs the debug adapters for you
'williamboman/mason.nvim',
'jay-babu/mason-nvim-dap.nvim',
-- Add your own debuggers here
'leoluz/nvim-dap-go',
},
config = function()
local dap = require('dap')
local dapui = require('dapui')
require('mason-nvim-dap').setup({
-- Makes a best effort to setup the various debuggers with
-- reasonable debug configurations
automatic_installation = true,
automatic_setup = true,
-- You can provide additional configuration to the handlers,
-- see mason-nvim-dap README for more information
handlers = {},
-- You'll need to check that you have the required things installed
-- online, please don't ask me how to install them :)
ensure_installed = {
-- Update this to ensure that you have the debuggers for the langs you want
'delve',
},
})
-- Basic debugging keymaps, feel free to change to your liking!
vim.keymap.set('n', '<F5>', dap.continue, { desc = 'Debug: Start/Continue' })
vim.keymap.set('n', '<F1>', dap.step_into, { desc = 'Debug: Step Into' })
vim.keymap.set('n', '<F2>', dap.step_over, { desc = 'Debug: Step Over' })
vim.keymap.set('n', '<F3>', dap.step_out, { desc = 'Debug: Step Out' })
vim.keymap.set('n', '<leader>b', dap.toggle_breakpoint, { desc = 'Debug: Toggle Breakpoint' })
vim.keymap.set('n', '<leader>B', function()
dap.set_breakpoint(vim.fn.input('Breakpoint condition: '))
end, { desc = 'Debug: Set Breakpoint' })
-- Dap UI setup
-- For more information, see |:help nvim-dap-ui|
dapui.setup({
-- Set icons to characters that are more likely to work in every terminal.
-- Feel free to remove or use ones that you like more! :)
-- Don't feel like these are good choices.
icons = { expanded = '', collapsed = '', current_frame = '*' },
controls = {
icons = {
pause = '',
play = '',
step_into = '',
step_over = '',
step_out = '',
step_back = 'b',
run_last = '▶▶',
terminate = '',
disconnect = '',
},
},
})
-- Toggle to see last session result. Without this, you can't see session output in case of unhandled exception.
vim.keymap.set('n', '<F7>', dapui.toggle, { desc = 'Debug: See last session result.' })
dap.listeners.after.event_initialized['dapui_config'] = dapui.open
dap.listeners.before.event_terminated['dapui_config'] = dapui.close
dap.listeners.before.event_exited['dapui_config'] = dapui.close
-- Install golang specific config
require('dap-go').setup()
end,
}

126
lua/plugins/floaterminal.lua Executable file
View file

@ -0,0 +1,126 @@
local M = {}
-- State to manage the floating terminal
M.state = {
floating = {
buf = -1,
win = -1,
},
}
-- Helper function to validate a window
local function is_valid_window(win)
return win and vim.api.nvim_win_is_valid(win)
end
-- Helper function to validate a buffer
local function is_valid_buffer(buf)
return buf and vim.api.nvim_buf_is_valid(buf)
end
-- Create or update the floating terminal
local function create_floating_terminal(opts)
opts = opts or {}
-- Calculate dimensions and position
local width = opts.width or math.floor(vim.o.columns * 0.8)
local height = opts.height or math.floor(vim.o.lines * 0.8)
local col = math.floor((vim.o.columns - width) / 2)
local row = math.floor((vim.o.lines - height) / 2)
-- Ensure buffer is valid or create a new one
local buf = is_valid_buffer(opts.buf) and opts.buf or vim.api.nvim_create_buf(false, true)
-- Window configuration
local win_config = {
relative = 'editor',
width = width,
height = height,
col = col,
row = row,
style = 'minimal',
border = opts.border or 'rounded',
title = opts.title or 'Terminal',
title_pos = 'center',
}
-- Create the floating window
local ok, win = pcall(vim.api.nvim_open_win, buf, true, win_config)
if not ok then
vim.notify('Failed to create floating window: ' .. win, vim.log.levels.ERROR)
return nil
end
return { buf = buf, win = win }
end
-- Toggle the floating terminal
function M.toggle_terminal(opts)
opts = opts or {}
if not is_valid_window(M.state.floating.win) then
-- Create and initialize the floating terminal
M.state.floating = create_floating_terminal({
buf = M.state.floating.buf,
width = opts.width,
height = opts.height,
border = opts.border,
title = opts.title,
})
if M.state.floating and is_valid_buffer(M.state.floating.buf) then
-- Ensure the buffer is a terminal
local buf = M.state.floating.buf
if vim.bo[buf].buftype ~= 'terminal' then
vim.api.nvim_set_current_buf(buf)
vim.cmd('startinsert')
vim.fn.termopen(os.getenv('SHELL') or 'sh')
end
end
else
-- Close the floating window
pcall(vim.api.nvim_win_close, M.state.floating.win, true)
M.state.floating.win = nil
end
end
-- Setup function to initialize the module
function M.setup(opts)
opts = opts or {}
-- Create a user command for toggling the terminal
vim.api.nvim_create_user_command('FloatTermToggle', function()
M.toggle_terminal(opts)
end, {})
-- Apply key mappings
M.keys(opts.mapping)
end
-- Apply key mappings
function M.keys(mapping)
local default_keymap = {
['<leader>ft'] = {
mode = { 'n', 't' },
cmd = '<CMD>FloatTermToggle<CR>',
options = { noremap = true, silent = true, desc = 'Toggle floating terminal' },
},
}
-- Use custom or default mappings
local keymaps = mapping or default_keymap
for key, map in pairs(keymaps) do
if map.desc then
map.options = vim.tbl_extend('force', map.options or {}, { desc = map.desc })
end
for _, mode in ipairs(map.mode) do
pcall(vim.keymap.del, mode, key)
end
vim.keymap.set(map.mode, key, map.cmd, map.options)
end
end
return M