Intelligent paste for Python - automatically adjusts indentation to match the current context.
- Smart indentation - Automatically adjusts pasted code to match context
- Treesitter support - AST-based indentation detection with intelligent fallback
- Dual usage modes - Toggle mode OR bind custom keys with parameters
- Vim registers - Uses Vim's default register, integrates seamlessly with
yy/p - File indent detection - Auto-detect the indentation width of the current file
Install with your plugin manager. Example for lazy.nvim:
{
"ZreXoc/smart-paste.nvim",
ft = "python",
opts = {},
}Mode 1: Toggle Mode (Default)
- Enable smart paste:
<leader>ptor:SmartPasteToggle - Copy code:
yy - Paste:
porP(works in smart mode) - Toggle off when not needed:
<leader>pt
Mode 2: Custom Bindings Create dedicated keymaps for specific behaviors:
-- Smart paste with 8-space indent
vim.keymap.set("n", "<leader>p8", function()
require("smart-paste").paste({ indent_width = 8 })
end)
-- Smart paste from clipboard
vim.keymap.set("n", "<leader>p+", function()
require("smart-paste").paste({ register = "+" })
end)
-- Smart paste (fallback mode)
vim.keymap.set("n", "<leader>pf", function()
require("smart-paste").paste({ use_treesitter = false })
end)Both modes can be used together - toggle for quick smart paste, or use custom bindings for specific needs.
When available, the plugin uses Treesitter to analyze the AST (Abstract Syntax Tree) of your Python code:
- Analyzes code structure (
class,function,if,for,while, etc.) - Detects nested blocks with high precision
- Handles edge cases like class methods and nested functions
When Treesitter is not available or explicitly disabled, the plugin uses a simple but reliable fallback:
- Finds the previous non-empty, non-comment line above the cursor
- Uses that line's indentation as the target level
- Works without any external dependencies
Use fallback mode if:
- You want faster performance
- Treesitter is not installed
- You prefer simpler detection logic
Enable fallback mode:
require("smart-paste").paste({ use_treesitter = false })Auto-detect the indentation width used in the current file:
-- Command line
:lua print(require("smart-paste.indent").detect_file_indent())
-- In a custom command
vim.api.nvim_create_user_command("DetectIndent", function()
local indent = require("smart-paste.indent").detect_file_indent()
if indent then
vim.notify("File indent: " .. indent .. " spaces")
else
vim.notify("Could not detect indentation")
end
end)| Command | Action |
|---|---|
:SmartPasteToggle |
Toggle between smart and default mode |
:SmartPasteEnable |
Enable smart paste |
:SmartPasteDisable |
Disable smart paste |
:SmartPasteStatus |
Show current status |
require("smart-paste").setup({
enabled = false, -- Disabled by default
indent_width = 4, -- Indentation width in spaces
indent_char = " ", -- Indentation character
use_treesitter = true, -- Use Treesitter when available
register = '"', -- Vim register to use
debug = false, -- Debug output
keymaps = {
toggle = "<leader>pt", -- Toggle shortcut
},
})Execute smart paste with optional parameters.
Parameters:
{
mode = "p", -- 'p' (after cursor) or 'P' (before cursor)
register = '"', -- Register: '"' (unnamed), '+' (clipboard), 'a'-'z' (named)
indent_width = 4, -- Override global indent width
tabwidth = 4, -- Alias for indent_width
use_treesitter = true, -- Use Treesitter for detection
indent_char = " ", -- Indentation character
debug = false, -- Enable debug output
}Examples:
-- Basic paste
require("smart-paste").paste()
-- Custom indent width
require("smart-paste").paste({ indent_width = 8 })
-- From system clipboard
require("smart-paste").paste({ register = "+" })
-- Use fallback mode only
require("smart-paste").paste({ use_treesitter = false })Initialize the plugin with configuration options.
require("smart-paste").toggle() -- Toggle smart/default mode
require("smart-paste").enable() -- Enable smart mode
require("smart-paste").disable() -- Disable smart mode
require("smart-paste").is_enabled() -- Get current status (returns boolean)Add to your init.lua:
-- Custom indent widths
vim.keymap.set("n", "<leader>p4", function()
require("smart-paste").paste({ indent_width = 4 })
end, { desc = "Smart paste (4-space)" })
vim.keymap.set("n", "<leader>p8", function()
require("smart-paste").paste({ indent_width = 8 })
end, { desc = "Smart paste (8-space)" })
-- From system clipboard
vim.keymap.set("n", "<leader>p+", function()
require("smart-paste").paste({ register = "+" })
end, { desc = "Smart paste from clipboard" })
-- Named registers
vim.keymap.set("n", "<leader>pa", function()
require("smart-paste").paste({ register = "a" })
end, { desc = "Smart paste from register a" })
-- Fallback mode without Treesitter
vim.keymap.set("n", "<leader>pf", function()
require("smart-paste").paste({ use_treesitter = false })
end, { desc = "Smart paste (fallback mode)" })vim.api.nvim_create_user_command("SmartPaste8", function()
require("smart-paste").paste({ indent_width = 8 })
end, { desc = "Smart paste with 8-space indent" })
-- Usage: :SmartPaste8Treesitter Mode (default):
- Analyzes the AST at the cursor position
- Identifies code blocks (function, class, if/for/while, etc.)
- Calculates indentation based on nesting level
- More accurate and context-aware
Fallback Mode:
- Finds the nearest non-empty, non-comment line above
- Uses that line's indentation level
- Simple and reliable, no dependencies
- Detects the base indentation of pasted content
- Calculates the difference (target - base)
- Applies adjustment to each line
Detect the indentation width of the current file:
local indent = require("smart-paste.indent").detect_file_indent()
if indent then
print("File uses " .. indent .. "-space indents")
endMIT