Skip to content

Commit c96a017

Browse files
fix: re-apply paste fix and unify with Windows improvements
1 parent 7c32676 commit c96a017

7 files changed

Lines changed: 58 additions & 10 deletions

File tree

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ let g:claude_code_map_zoom = '<C-w>z'
242242
| Normal | `<Leader>cV` | Toggle with `--verbose` |
243243
| Terminal | `<C-\>` | Hide Claude Code terminal |
244244
| Terminal | `<C-w>z` | **Zoom Toggle**: Maximize or restore terminal |
245+
| Terminal | `<C-v>` | **Paste**: Paste system clipboard content |
245246
| Terminal | `<C-h/j/k/l>` | Navigate to adjacent window |
246247

247248
### Extended keymaps (`g:claude_code_map_extended_prefix` + key)
@@ -307,6 +308,7 @@ let g:claude_code_float_border = 'double'
307308
| `g:claude_code_map_extended_keys` | `1` | Register `<Leader>c*` keymaps |
308309
| `g:claude_code_map_toggle` | `'<C-\>'` | Toggle key |
309310
| `g:claude_code_map_zoom` | `'<C-w>z'` | Zoom key |
311+
| `g:claude_code_map_paste` | `'<C-v>'` | Paste key |
310312
| `g:claude_code_map_continue` | `'<Leader>cC'` | Continue key |
311313
| `g:claude_code_map_verbose` | `'<Leader>cV'` | Verbose key |
312314
| `g:claude_code_map_extended_prefix` | `'<Leader>c'` | Prefix for all extended keymaps |
@@ -319,6 +321,7 @@ let g:claude_code_float_border = 'double'
319321
| `g:claude_code_model` | `''` | Claude model override |
320322
| `g:claude_code_debug` | `0` | Enable debug logging to message area |
321323
| `g:claude_code_diff_preview` | `0` | Auto-start diff preview polling on Vim startup |
324+
| `g:claude_code_bracketed_paste` | `1` | Enable bracketed paste mode support |
322325
| `g:claude_code_terminal_start_delay` | `300` | Delay (ms) before attaching to Claude terminal |
323326

324327
Buffer-local `b:claude_code_*` overrides take precedence over `g:` variables.

autoload/claude_code/config.vim

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ let s:defaults = {
3434
\ 'map_continue': '<Leader>cC',
3535
\ 'map_verbose': '<Leader>cV',
3636
\ 'map_zoom': '<C-w>z',
37+
\ 'map_paste': '<C-v>',
38+
\ 'bracketed_paste': 1,
3739
\ 'debug': 0,
3840
\ 'terminal_start_delay': 300,
3941
\ 'scroll_keys': 1,

autoload/claude_code/git.vim

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,16 @@ function! claude_code#git#root() abort
1919
return s:git_root_cache[l:cwd]
2020
endif
2121

22-
let s:output_redirect = ' 2>/dev/null'
23-
if has("win32")
24-
let s:output_redirect = ' 2>nul'
25-
endif
22+
let l:null = has('win32') ? 'nul' : '/dev/null'
23+
let l:redirect = ' 2>' . l:null
2624

27-
let l:inside = system('git -C ' . shellescape(l:cwd) . ' rev-parse --is-inside-work-tree' . s:output_redirect)
25+
let l:inside = system('git -C ' . shellescape(l:cwd) . ' rev-parse --is-inside-work-tree' . l:redirect)
2826
if v:shell_error || trim(l:inside) !=# 'true'
2927
let s:git_root_cache[l:cwd] = ''
3028
return ''
3129
endif
3230

33-
let l:root = trim(system('git -C ' . shellescape(l:cwd) . ' rev-parse --show-toplevel' . s:output_redirect))
31+
let l:root = trim(system('git -C ' . shellescape(l:cwd) . ' rev-parse --show-toplevel' . l:redirect))
3432
if v:shell_error
3533
let s:git_root_cache[l:cwd] = ''
3634
return ''

autoload/claude_code/keymaps.vim

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,19 @@ function! claude_code#keymaps#setup_terminal(bufnr) abort
1919
execute 'tnoremap <buffer> <silent> <C-l> <C-\><C-n><C-w>l'
2020
execute 'tnoremap <buffer> <silent> ' . claude_code#config#get('map_zoom') . ' <C-\><C-n>:Claude zoom<CR>'
2121

22+
" Paste from system clipboard
23+
let l:paste_key = claude_code#config#get('map_paste')
24+
if !empty(l:paste_key)
25+
execute 'tnoremap <buffer> <silent> ' . l:paste_key . ' <C-\><C-n>:call claude_code#terminal#paste()<CR>'
26+
endif
27+
28+
" Bracketed paste support
29+
if claude_code#config#get('bracketed_paste')
30+
" This allows Vim to handle the escape sequence sent by terminal emulators
31+
" during a paste. We bridge it to our mapping-free paste function.
32+
execute 'tnoremap <buffer> <silent> <Esc>[200~ <C-\><C-n>:call claude_code#terminal#paste()<CR>'
33+
endif
34+
2235
" Mouse/touchpad scroll in terminal mode: escape to Normal, scroll, stay in
2336
" Normal so the user can keep reading. Vim passes raw ScrollWheel events
2437
" through to the running program when in terminal mode, so we must intercept

autoload/claude_code/meta_commands.vim

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ function! claude_code#meta_commands#version() abort
9191
\ ]
9292

9393
if executable('claude')
94-
let l:cli_ver = trim(system('claude --version 2>/dev/null'))
94+
let l:null = has('win32') ? 'nul' : '/dev/null'
95+
let l:cli_ver = trim(system('claude --version 2>' . l:null))
9596
if v:shell_error || empty(l:cli_ver)
9697
let l:cli_ver = '(could not determine)'
9798
endif

autoload/claude_code/terminal.vim

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,18 +145,38 @@ function! s:instance_cwd(instance_id) abort
145145
return ''
146146
endif
147147
" Normalise both sides to forward slashes for a reliable comparison.
148-
let l:inst = substitute(a:instance_id, '\\', '/', 'g')
149-
let l:cwd = substitute(getcwd(), '\\', '/', 'g')
148+
let l:inst = tr(a:instance_id, '\', '/')
149+
let l:cwd = tr(getcwd(), '\', '/')
150150
if l:inst ==# l:cwd
151151
return ''
152152
endif
153153
" Return an OS-native path so term_start's cwd option works on all platforms.
154154
if has('win32')
155-
return substitute(a:instance_id, '/', '\\', 'g')
155+
return tr(a:instance_id, '/', '\')
156156
endif
157157
return a:instance_id
158158
endfunction
159159

160+
" Paste from system clipboard into the terminal buffer.
161+
" Bypasses terminal mappings using term_sendkeys().
162+
function! claude_code#terminal#paste() abort
163+
let l:bnr = bufnr('%')
164+
if getbufvar(l:bnr, '&buftype') !=# 'terminal'
165+
return
166+
endif
167+
168+
" Use + register (system clipboard) if available, fallback to * or default.
169+
let l:reg = has('clipboard') ? '+' : '"'
170+
let l:text = getreg(l:reg)
171+
if empty(l:text) && l:reg == '+'
172+
let l:text = getreg('*')
173+
endif
174+
175+
if !empty(l:text)
176+
call term_sendkeys(l:bnr, l:text)
177+
endif
178+
endfunction
179+
160180
" Create a brand-new Claude Code terminal.
161181
function! s:create_new(instance_id) abort
162182
call claude_code#util#debug('terminal: creating new instance for ' . a:instance_id)

doc/claude_code.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,7 @@ Default terminal keymaps (when |g:claude_code_map_keys| is 1):
313313
Terminal mode (inside the Claude window): ~
314314
<C-\> Hide Claude Code terminal
315315
<C-w>z Zoom Toggle: Maximize or restore terminal
316+
<C-v> Paste: Paste system clipboard content
316317
<C-h/j/k/l> Navigate to adjacent window
317318

318319
Extended keymaps (when g:claude_code_map_extended_keys is 1):
@@ -423,6 +424,11 @@ g:claude_code_map_toggle Default: '<C-\>'
423424
*g:claude_code_map_zoom*
424425
g:claude_code_map_zoom Default: '<C-w>z'
425426
Key to toggle the zoomed (maximized) state.
427+
428+
*g:claude_code_map_paste*
429+
g:claude_code_map_paste Default: '<C-v>'
430+
Key to paste text from the system clipboard into the terminal.
431+
Bypasses terminal mappings using |term_sendkeys()|.
426432

427433
*g:claude_code_map_continue*
428434
g:claude_code_map_continue Default: '<Leader>cC'
@@ -477,6 +483,11 @@ g:claude_code_diff_preview Default: 0
477483
register the hooks. >
478484
let g:claude_code_diff_preview = 1
479485
<
486+
*g:claude_code_bracketed_paste*
487+
g:claude_code_bracketed_paste Default: 1
488+
Enable bracketed paste mode support. When enabled, terminal emulator
489+
pastes (e.g. Ctrl-Shift-V) are captured and sent via |term_sendkeys()|
490+
to avoid triggering Vim mappings.
480491

481492
*g:claude_code_terminal_start_delay*
482493
g:claude_code_terminal_start_delay Default: 300

0 commit comments

Comments
 (0)