|
| 1 | +# copy_with_context.nvim |
| 2 | + |
| 3 | +## Project Overview |
| 4 | + |
| 5 | +copy_with_context.nvim is a Neovim plugin that simplifies sharing code snippets by automatically copying selected lines along with their file path and line number metadata. This eliminates the manual process of adding context information when sharing code, making collaboration and code review more efficient. |
| 6 | + |
| 7 | +## Purpose |
| 8 | + |
| 9 | +When sharing code snippets with teammates, in documentation, or during code reviews, it's essential to provide context about where the code is located. This plugin automates that process by: |
| 10 | +- Copying the selected code/line(s) |
| 11 | +- Automatically appending file path and line number(s) as a comment |
| 12 | +- Supporting both relative and absolute file paths |
| 13 | +- Working with both single lines and visual selections |
| 14 | + |
| 15 | +## Key Features |
| 16 | + |
| 17 | +- **Single Line Copy**: Copy the current line with context using a simple keymap |
| 18 | +- **Visual Selection**: Copy multiple lines with a line range indicator |
| 19 | +- **Flexible Path Options**: Choose between relative or absolute file paths |
| 20 | +- **Customizable Format**: Configure the context comment format to match your needs |
| 21 | +- **Optional Line Trimming**: Choose whether to trim whitespace from copied lines |
| 22 | +- **Configurable Keymaps**: Set your own preferred key mappings |
| 23 | + |
| 24 | +## Architecture |
| 25 | + |
| 26 | +### File Structure |
| 27 | + |
| 28 | +``` |
| 29 | +copy_with_context.nvim/ |
| 30 | +├── lua/copy_with_context/ |
| 31 | +│ ├── init.lua # Plugin entry point and setup function |
| 32 | +│ ├── config.lua # Configuration management and defaults |
| 33 | +│ ├── main.lua # Core copy functionality and keymap setup |
| 34 | +│ └── utils.lua # Utility functions (line extraction, formatting, clipboard) |
| 35 | +├── plugin/ |
| 36 | +│ └── copy_with_context.lua # Plugin loader |
| 37 | +├── doc/ |
| 38 | +│ └── copy_with_context.txt # Vim help documentation |
| 39 | +└── tests/ |
| 40 | + └── copy_with_context/ # Test suite using busted |
| 41 | +``` |
| 42 | + |
| 43 | +### Module Responsibilities |
| 44 | + |
| 45 | +**init.lua** (lua/copy_with_context/init.lua:1) |
| 46 | +- Entry point for the plugin |
| 47 | +- Delegates to config and main modules |
| 48 | +- Provides the `setup()` function users call |
| 49 | + |
| 50 | +**config.lua** (lua/copy_with_context/config.lua:1) |
| 51 | +- Stores default configuration |
| 52 | +- Merges user-provided options with defaults |
| 53 | +- Manages: |
| 54 | + - Key mappings (relative/absolute path shortcuts) |
| 55 | + - Context format string |
| 56 | + - Line trimming preference |
| 57 | + |
| 58 | +**main.lua** (lua/copy_with_context/main.lua:1) |
| 59 | +- Core functionality: `copy_with_context(absolute_path, is_visual)` |
| 60 | +- Sets up keymaps for normal and visual modes |
| 61 | +- Orchestrates the copy operation |
| 62 | +- Provides user feedback via `nvim_echo` |
| 63 | + |
| 64 | +**utils.lua** (lua/copy_with_context/utils.lua:1) |
| 65 | +- `get_lines(is_visual)`: Extracts lines from buffer |
| 66 | +- `get_file_path(absolute)`: Gets file path (relative or absolute) |
| 67 | +- `format_line_range(start, end)`: Formats line numbers (e.g., "5" or "5-10") |
| 68 | +- `process_lines(lines)`: Applies trim_lines setting if enabled |
| 69 | +- `copy_to_clipboard(output)`: Copies to both `*` and `+` registers |
| 70 | +- `format_output(content, path, range)`: Combines code and context comment |
| 71 | + |
| 72 | +## Configuration |
| 73 | + |
| 74 | +### Default Settings |
| 75 | + |
| 76 | +```lua |
| 77 | +{ |
| 78 | + mappings = { |
| 79 | + relative = "<leader>cy", -- Copy with relative path |
| 80 | + absolute = "<leader>cY", -- Copy with absolute path |
| 81 | + }, |
| 82 | + context_format = "# %s:%s", -- Comment format: "# filepath:line" |
| 83 | + trim_lines = false, -- Preserve leading/trailing whitespace |
| 84 | +} |
| 85 | +``` |
| 86 | + |
| 87 | +### Setup Example |
| 88 | + |
| 89 | +```lua |
| 90 | +require('copy_with_context').setup({ |
| 91 | + mappings = { |
| 92 | + relative = '<leader>cy', |
| 93 | + absolute = '<leader>cY' |
| 94 | + }, |
| 95 | + trim_lines = false, |
| 96 | + context_format = '# %s:%s', -- Can be customized to any format |
| 97 | +}) |
| 98 | +``` |
| 99 | + |
| 100 | +## Usage |
| 101 | + |
| 102 | +### Normal Mode |
| 103 | +- `<leader>cy`: Copy current line with relative path |
| 104 | +- `<leader>cY`: Copy current line with absolute path |
| 105 | + |
| 106 | +### Visual Mode |
| 107 | +- Select lines, then `<leader>cy`: Copy selection with relative path |
| 108 | +- Select lines, then `<leader>cY`: Copy selection with absolute path |
| 109 | + |
| 110 | +### Output Format Examples |
| 111 | + |
| 112 | +**Single line with relative path:** |
| 113 | +``` |
| 114 | + <% posts.each do |post| %> |
| 115 | + # app/views/widgets/show.html.erb:4 |
| 116 | +``` |
| 117 | + |
| 118 | +**Multiple lines with absolute path:** |
| 119 | +``` |
| 120 | + <% posts.each do |post| %> |
| 121 | + <%= post.title %> |
| 122 | + <% end %> |
| 123 | + # /Users/zh/dev/project_name/app/views/widgets/show.html.erb:4-6 |
| 124 | +``` |
| 125 | + |
| 126 | +## Development |
| 127 | + |
| 128 | +### Prerequisites |
| 129 | +- Neovim 0.7.0+ |
| 130 | +- Lua 5.1+ |
| 131 | +- Cargo (for stylua) |
| 132 | + |
| 133 | +### Setup |
| 134 | +```bash |
| 135 | +git clone https://github.com/zhisme/copy_with_context.nvim |
| 136 | +cd copy_with_context.nvim |
| 137 | +make deps # Install development dependencies |
| 138 | +``` |
| 139 | + |
| 140 | +### Testing |
| 141 | +The project uses [busted](https://lunarmodules.github.io/busted/) for testing: |
| 142 | +```bash |
| 143 | +make test # Run test suite |
| 144 | +``` |
| 145 | + |
| 146 | +Test files are located in `tests/copy_with_context/`: |
| 147 | +- `config_spec.lua`: Configuration tests |
| 148 | +- `main_spec.lua`: Core functionality tests |
| 149 | +- `utils_spec.lua`: Utility function tests |
| 150 | + |
| 151 | +### Code Quality |
| 152 | +```bash |
| 153 | +make lint # Run luacheck |
| 154 | +make fmt # Format code with stylua |
| 155 | +make fmt-check # Check formatting |
| 156 | +``` |
| 157 | + |
| 158 | +### Local Testing |
| 159 | + |
| 160 | +**With packer.nvim:** |
| 161 | +```lua |
| 162 | +use { |
| 163 | + "~/path/to/copy_with_context.nvim", |
| 164 | + config = function() |
| 165 | + require('copy_with_context').setup({ |
| 166 | + mappings = { |
| 167 | + relative = '<leader>cy', |
| 168 | + absolute = '<leader>cY' |
| 169 | + }, |
| 170 | + trim_lines = false, |
| 171 | + context_format = '# %s:%s', |
| 172 | + }) |
| 173 | + end |
| 174 | +} |
| 175 | +``` |
| 176 | + |
| 177 | +**With lazy.nvim:** |
| 178 | +```lua |
| 179 | +{ |
| 180 | + dir = "~/path/to/copy_with_context.nvim", |
| 181 | + dev = true, |
| 182 | + opts = { |
| 183 | + mappings = { |
| 184 | + relative = '<leader>cy', |
| 185 | + absolute = '<leader>cY' |
| 186 | + }, |
| 187 | + trim_lines = false, |
| 188 | + context_format = '# %s:%s', |
| 189 | + } |
| 190 | +} |
| 191 | +``` |
| 192 | + |
| 193 | +## Technical Details |
| 194 | + |
| 195 | +### Clipboard Integration |
| 196 | +The plugin copies to both the `*` (system selection) and `+` (system clipboard) registers for maximum compatibility across different systems. |
| 197 | + |
| 198 | +### Visual Mode Support |
| 199 | +Uses Vim's marks `'<` and `'>` to get the visual selection range, ensuring accurate line extraction even after exiting visual mode. |
| 200 | + |
| 201 | +### Path Handling |
| 202 | +- Relative path: Uses `vim.fn.expand("%")` |
| 203 | +- Absolute path: Uses `vim.fn.expand("%:p")` |
| 204 | + |
| 205 | +## Contributing |
| 206 | + |
| 207 | +Contributions are welcome! Please: |
| 208 | +1. Write tests for new features |
| 209 | +2. Ensure all tests pass (`make test`) |
| 210 | +3. Run linters (`make lint`) |
| 211 | +4. Format code (`make fmt`) |
| 212 | +5. Provide clear descriptions in PRs |
| 213 | + |
| 214 | +## License |
| 215 | + |
| 216 | +MIT License |
| 217 | + |
| 218 | +## Links |
| 219 | + |
| 220 | +- Repository: https://github.com/zhisme/copy_with_context.nvim |
| 221 | +- Issues: https://github.com/zhisme/copy_with_context.nvim/issues |
| 222 | +- Author: Evgeny Zhdanov (evdev34@gmail.com) |
0 commit comments