https://github.com/dmtrkovalenko/fold-imports.nvim
Neovim plugin to automatically fold imports in any language using treesitter
https://github.com/dmtrkovalenko/fold-imports.nvim
neovim-plugin
Last synced: 9 months ago
JSON representation
Neovim plugin to automatically fold imports in any language using treesitter
- Host: GitHub
- URL: https://github.com/dmtrkovalenko/fold-imports.nvim
- Owner: dmtrKovalenko
- License: mit
- Created: 2025-07-18T22:10:34.000Z (11 months ago)
- Default Branch: main
- Last Pushed: 2025-07-23T21:08:44.000Z (11 months ago)
- Last Synced: 2025-09-04T18:53:45.511Z (9 months ago)
- Topics: neovim-plugin
- Language: Lua
- Homepage:
- Size: 47.9 KB
- Stars: 46
- Watchers: 0
- Forks: 2
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# fold-imports.nvim


A Neovim plugin that automatically folds import/export statements in multiple programming languages using treesitter. Reduces visual clutter by folding verbose import blocks and showing the CODE.
https://github.com/user-attachments/assets/a1c54774-ee8a-4595-9653-bc400a34336a
## Installation
### Using [lazy.nvim](https://github.com/folke/lazy.nvim)
```lua
{
"dmtrKovalenko/fold-imports.nvim",
opts = {},
event = "BufRead"
}
```
### Using [packer.nvim](https://github.com/wbthomason/packer.nvim)
```lua
use {
"dmtrKovalenko/fold-imports.nvim",
config = function()
require("fold_imports").setup()
end,
}
```
## Quick Start
The plugin works out of the box with zero configuration:
```lua
require("fold_imports").setup()
```
Open any supported file and imports will be automatically folded.
## Configuration
### Default Configuration
```lua
require("fold_imports").setup({{
enabled = true,
auto_fold = true,
fold_level = 0,
-- refolds imports after lsp code edits (e.g. code actions)
auto_fold_after_code_action = true,
-- custom fold text for import sections
custom_fold_text = true,
fold_text_format = "Folded imports (%d lines)",
-- maximum lines for a single import statement to be considered for folding
max_import_lines = 50,
languages = {
typescript = {
enabled = true,
parsers = { "typescript", "tsx" },
queries = {
"(import_statement) @import",
"(export_statement (export_clause) @export)",
},
filetypes = { "typescript", "typescriptreact" },
patterns = { "*.ts", "*.tsx" },
},
javascript = {
enabled = true,
parsers = { "javascript", "jsx" },
queries = {
"(import_statement) @import",
"(export_statement (export_clause) @export)",
},
filetypes = { "javascript", "javascriptreact" },
patterns = { "*.js", "*.jsx", "*.mjs" },
},
rust = {
enabled = true,
parsers = { "rust" },
queries = {
"(use_declaration) @import",
"(mod_item) @import",
},
filetypes = { "rust" },
patterns = { "*.rs" },
},
c = {
enabled = true,
parsers = { "c" },
queries = {
"(preproc_include) @import",
"(preproc_def) @import",
},
filetypes = { "c" },
patterns = { "*.c", "*.h" },
},
cpp = {
enabled = true,
parsers = { "cpp" },
queries = {
"(preproc_include) @import",
"(preproc_def) @import",
"(using_declaration) @import",
"(namespace_alias_definition) @import",
"(linkage_specification) @import",
},
filetypes = { "cpp" },
patterns = { "*.cpp", "*.cxx", "*.cc", "*.hpp", "*.hxx", "*.hh" },
},
ocaml = {
enabled = true,
parsers = { "ocaml" },
queries = {
"(open_module) @import",
},
filetypes = { "ocaml" },
patterns = { "*.ml", "*.mli" },
},
zig = {
enabled = true,
parsers = { "zig" },
queries = {
'(variable_declaration (identifier) (builtin_function (builtin_identifier) @builtin (#eq? @builtin "@import"))) @import',
},
filetypes = { "zig" },
patterns = { "*.zig" },
},
python = {
enabled = true,
parsers = { "python" },
queries = {
"(import_statement) @import",
"(import_from_statement) @import",
"(future_import_statement) @import",
},
filetypes = { "python" },
patterns = { "*.py", "*.pyi" },
},
go = {
enabled = true,
parsers = { "go" },
queries = {
"(import_declaration) @import", -- For import blocks
"(import_spec) @import", -- For individual imports within blocks
},
filetypes = { "go" },
patterns = { "*.go" },
},
dart = {
enabled = true,
parsers = { "dart" },
queries = {
"(import_or_export) @import",
},
filetypes = { "dart" },
patterns = { "*.dart" },
},
},
}})
```
### Custom Language Configuration
Disable specific languages or add custom Tree-sitter queries:
```lua
require("fold_imports").setup({
languages = {
-- Disable TypeScript folding
typescript = {
enabled = false,
},
-- Add your language with a query
python = {
enabled = true,
queries = {
-- To see what to put here run `:InspectTree` and put cursor over the import statement
"(import_statement) @import",
"(import_from_statement) @import",
},
},
},
})
```
### Disable Auto-folding
For manual control only:
```lua
require("fold_imports").setup({
auto_fold = false,
})
```
Then use `:FoldImports` command to fold imports manually.
## Commands
| Command | Description |
| -------------------- | ------------------------------------------------ |
| `:FoldImports` | Manually fold imports in the current buffer |
| `:FoldImportsToggle` | Enable/disable the plugin |
| `:FoldImportsDebug` | Debug Tree-sitter matches for the current buffer |
## API
The plugin exposes a Lua API for programmatic control:
```lua
local fold_imports = require("fold_imports")
-- Manually fold imports
fold_imports.fold_imports()
-- Enable the plugin
fold_imports.enable()
-- Disable the plugin
fold_imports.disable()
-- Toggle the plugin
fold_imports.toggle()
```
## How It Works
1. **Tree-sitter Integration**: Uses Tree-sitter parsers to accurately identify import statements in different languages
2. **Smart Grouping**: Groups adjacent import statements, ignoring empty lines between them
3. **Intelligent Folding**: Creates folds for:
- Multi-line import groups
- Multiple separate import groups
- Single-line imports when there are multiple imports total
4. **LSP Integration**: Monitors LSP text edits and re-folds imports when changes occur near existing import folds
5. **Performance**: Uses retries with exponential backoff and optimizes the runtime
6. Git Conflicts detection: Detects git conflicts using various popular plugins like [git-conflict.nvim](https://github.com/akinsho/git-conflict.nvim)
## Language Support
### TypeScript/JavaScript
- **Supported**: Import declarations, export statements with export clauses
- **Examples**: `import { foo } from 'bar'`, `export { baz }`
### Rust
- **Supported**: Use declarations, module items
- **Examples**: `use std::collections::HashMap;`, `mod utils;`
### Python
- **Supported**: Import statements, from-import statements, future imports
- **Examples**: `import os`, `from typing import List`, `from __future__ import annotations`
### C/C++
- **Supported**: Preprocessor includes, defines, using declarations (C++), namespace aliases (C++)
- **Examples**: `#include `, `using namespace std;`
### OCaml
- **Supported**: Open module statements
- **Examples**: `open List`, `open Printf`
### Zig
- **Supported**: Variable declarations with @import builtin
- **Examples**: `const std = @import("std");`
### go
- **Supported**: Import statements
- **Examples**: `import fmt`
## Troubleshooting
### Imports Not Folding
1. **Check Tree-sitter parser**: Ensure the required Tree-sitter parser is installed:
```vim
:TSInstall typescript javascript rust python c cpp ocaml zig
```
2. **Debug Tree-sitter matches**: Use the debug command to see what's being detected:
```vim
:FoldImportsDebug
```
3. **Verify filetype**: Check that your file has the correct filetype:
```vim
:set filetype?
```
### Custom Queries Not Working
Tree-sitter queries are language-specific. Use `:TSPlayground` to explore the syntax tree and write custom queries. The query format follows Tree-sitter query syntax.
## Requirements
- **Neovim**: >= 0.8.0
- **Tree-sitter**: Built-in Neovim Tree-sitter support
- **Parsers**: Language-specific Tree-sitter parsers (installed via `:TSInstall`)
## License
MIT License - see [LICENSE](LICENSE) file for details.
## Author
Created by [@neogoose_btw](https://x.com/neogoose_btw)
Built with [tree-sitter](https://tree-sitter.github.io/) for accurate parsing. Template based on [nvim-plugin-template](https://github.com/ellisonleao/nvim-plugin-template).