mirror of
https://github.com/vim/vim.git
synced 2026-05-28 00:21:37 +02:00
29fa934344
Problem: runtime(osc52): triggered twice with TextPutPoste autocmd Solution: Detect recursive trigger and return null (Foxe Chen) closes: #20216 Signed-off-by: Foxe Chen <chen.foxe@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
113 lines
2.8 KiB
VimL
113 lines
2.8 KiB
VimL
vim9script
|
|
|
|
export var allowed: bool = false
|
|
|
|
export def Available(): bool
|
|
if get(g:, 'osc52_force_avail', 0)
|
|
return true
|
|
endif
|
|
return allowed
|
|
enddef
|
|
|
|
var sent_message: bool = false
|
|
|
|
def OSCMessage(id: number)
|
|
echo "Waiting for OSC52 response... Press CTRL-C to cancel"
|
|
sent_message = true
|
|
enddef
|
|
|
|
var loop_timerid: number = -1
|
|
|
|
export def Paste(reg: string): any
|
|
# Check if user has indicated that the terminal does not support OSC 52 paste
|
|
# (or has disabled it)
|
|
if get(g:, 'osc52_disable_paste', 0)
|
|
return ("c", [])
|
|
endif
|
|
|
|
if loop_timerid != -1
|
|
# This will result in the register being unchanged
|
|
return null
|
|
endif
|
|
|
|
# Some terminals like Kitty respect the selection type parameter on both X11
|
|
# and Wayland. If the terminal doesn't then the selection type parameter
|
|
# should be ignored (no-op)
|
|
if reg == "+"
|
|
echoraw("\<Esc>]52;c;?\<Esc>\\")
|
|
else
|
|
echoraw("\<Esc>]52;p;?\<Esc>\\")
|
|
endif
|
|
|
|
var timerid: number = timer_start(1000, OSCMessage)
|
|
var interrupt: bool = false
|
|
|
|
# Wait for response from terminal. If we got interrupted (Ctrl-C), then do a
|
|
# redraw if we already sent the message, and return an empty string.
|
|
try
|
|
while true
|
|
var key: string = getcharstr(-1, {cursor: "hide"})
|
|
|
|
if key == "\<xOSC>" && match(v:termosc, '52;') != -1
|
|
break
|
|
elseif key == "\<C-c>"
|
|
interrupt = true
|
|
break
|
|
endif
|
|
endwhile
|
|
|
|
# This doesn't seem to catch Ctrl-C sent via term_sendkeys(), which is used in
|
|
# tests. So also check the result of getcharstr()/getchar().
|
|
catch /^Vim:Interrupt$/
|
|
interrupt = true
|
|
finally
|
|
timer_stop(timerid)
|
|
if sent_message
|
|
sent_message = false
|
|
:redraw!
|
|
endif
|
|
endtry
|
|
|
|
# A TextPutPost autocmd may cause this function to be called twice, which is
|
|
# technically intended behaviour, however it is not necessary for this plugin.
|
|
# To prevent this, return immediately if we have not returned back to the main
|
|
# loop since the last "paste" call.
|
|
loop_timerid = timer_start(0, (_) => {
|
|
loop_timerid = -1
|
|
})
|
|
|
|
if interrupt
|
|
echo "Interrupted while waiting for OSC 52 response"
|
|
return ("c", [""])
|
|
endif
|
|
|
|
# Extract the base64 stuff
|
|
var stuff: string = matchstr(v:termosc, '52;.*;\zs[A-Za-z0-9+/=]*')
|
|
|
|
if len(stuff) == 0
|
|
return ("c", [])
|
|
endif
|
|
|
|
var ret: list<string>
|
|
|
|
# "stuff" may be an invalid base64 string, so catch any errors
|
|
try
|
|
ret = blob2str(base64_decode(stuff))
|
|
catch /E\(475\|1515\)/
|
|
echo "Invalid OSC 52 response received"
|
|
return ("c", [""])
|
|
endtry
|
|
|
|
return ("", ret)
|
|
enddef
|
|
|
|
export def Copy(reg: string, type: string, lines: list<string>): void
|
|
if reg == "+"
|
|
echoraw("\<Esc>]52;c;" .. base64_encode(str2blob(lines)) .. "\<Esc>\\")
|
|
else
|
|
echoraw("\<Esc>]52;p;" .. base64_encode(str2blob(lines)) .. "\<Esc>\\")
|
|
endif
|
|
enddef
|
|
|
|
# vim: set sw=2 sts=2 :
|