Tieni presente che dalla versione 292, xterm rimuove i caratteri di controllo ASCII tranne \ b
, \ r
, \ t
, DEL
(0x7f) e \ n
(converte \ n
in \ r
come altri terminali ) e puoi ripristinarli con la risorsa allowPasteControls
. Anche VTE (la libreria dell'emulatore di terminale usata da gnome-terminal
, terminator
, xfce-terminal
...) lo fa da ottobre 2015
Quindi, in quei terminali, ^ C
, ^ [
, ^ D
, ^ Z
, ^ \
, ^ U
, ^ W
non sono più un problema ma DEL, \ b
, \ t
(molto pericoloso con alcune configurazioni (inclusa quella predefinita) di zsh
dove il completamento può espandere le sostituzioni dei comandi), \ r
e \ n
lo sono ancora.
xterm
ha anche un paio di modalità di incolla che possono aiutare qui.
-
la modalità di incolla tra parentesi abilitata con la sequenza \ e [? 2004h
utilizzata in alcuni plug-in zsh o vim safe -paste.
zsh
( zle
) dalla 5.1 e bash
( readline
) dalla 4.4 ora hanno supporto per quello integrato. Sebbene sia abilitato per impostazione predefinita in zsh
, è necessario per abilitarlo manualmente con bind 'set enable-bracketed-paste on'
in bash
(o nella configurazione readline
in ~ / .inputrc
o /etc/inputrc
).
Questo avvolge la selezione tra \ e [200 ~
e \ e [201 ~
.
La maggior parte degli altri terminali moderni come quelli basati su VTE ( gnome-terminal
, xfce-terminal
, terminator
...), rxvt
, konsole
, OS / X Terminal
ora supportano anche quello.
In alcuni di questi altri terminali (o loro versioni) però (o con allowPasteControls
in xterm
), questo è difettoso in quel \ e [201 ~
potrebbe apparire nella selezione e verrebbe preso come parentesi di chiusura.
Ciò potrebbe essere risolto con parentesi come \ e \ e [201 ~ \ e [200 ~ 201 ~
, ma non è ancora fatto da nessun emulatore di terminale AFAIK (e significherebbe che l'applicazione vedrebbe diverse paste).
^ C
/ ^ Z
/ ^ \
causerebbe comunque l'invio di segnali al gruppo di processi in primo piano di il terminale se ISIG
non era disabilitato nella disciplina della riga tty.
-
La modalità incolla tra virgolette abilitata con \ e [? 2005h
sequenza (disabilitata con \e[?2005l
).
Questo antepone ogni carattere (in realtà byte) con un carattere ^ V
.
^ V
è il carattere predefinito lnext
( letterale successivo ) della disciplina di riga tty in modalità canonica ed è riconosciuto come tale anche da vi
e altri editor e alcuni editor di riga come readline o zle di zsh
.
Quello non ha lo stesso problema come la modalità tra parentesi sopra, e ha il vantaggio di funzionare per la modalità canonica del terminale (come quando esegui cat > file
) e poche altre applicazioni ma ne ha alcune svantaggi:
- newline e CR finiscono per essere visualizzati come ^ M . Ciò può essere evitato con un'altra sequenza di escape:
\ e [? 2006h
, ma ciò fa sì che le nuove righe vengano inserite come caratteri NUL in vim
e mostrate come ^ J
(a meno che tu non faccia stty -echoctl
) nella modalità canonica del terminale (sebbene sia solo un problema estetico). - Non funziona alla grande per multi- caratteri byte non inseriti correttamente in
zle
o vim
, ad esempio.
- alcune applicazioni visive non gestiscono
^ V
come letterale successivo , quindi potrebbe essere comunque necessario disattivarlo selettivamente. - puoi non lo uso in
vim
come ^ V 1
per esempio non inserisce 1
ma ^ A
lì. - Non sono a conoscenza di nessun altro terminale oltre a
xterm
che lo supporti, ma non ho condotto un sondaggio approfondito.
-
ti consente anche di definire la tua modalità di incolla tra parentesi tramite la configurazione. Ad esempio, con:
XTerm * allowPasteControls: true XTerm.VT100.translations: #override \ Ctrl Shift<KeyPress> Insert: \ insert-formatted ("\ 033 [202 ~% S ~% s" , APPUNTI, PRINCIPALE, CUT_BUFFER0) "
inserirà APPUNTI
/ PRIMARIO
/ CUT_BUFFER0
come ^ [[202 ~ <size-in-bytes> ~ <content>
su Maiusc + Ctrl + Inserisci . L'applicazione potrebbe quindi interpretarlo in modo affidabile (dovrebbe comunque disabilitare ISIG
nella disciplina della riga tty).
Un altro approccio sarebbe quello di usa uno pseudo-tty wrapper che inserisce quei ^ V
solo davanti ai caratteri di controllo. Tale wrapper dovrebbe essere in grado di rilevare i caratteri di controllo nelle paste con una certa affidabilità perché le reali pressioni dei tasti della tastiera invierebbero solo un carattere alla volta o una sequenza di caratteri che iniziano con ESC, mentre le paste ne invierebbero diversi alla volta .
Avresti ancora il problema delle nuove righe mostrate come ^ J
nella modalità canonica del terminale o ^ @
in vim
, ma questo potrebbe essere risolto con un po 'di collaborazione dalla shell
Una prova di concetto:
Da utilizzare ad esempio come:
./ safe-paste bash
Per avviare una shell bash
sotto quel wrapper.
#! / usr / bin / perluse IO :: Pty; usa IO :: Stty; my $ pty = new IO :: Pty; my $ pid = fork ();
die "Impossibile eseguire il fork" se non definito $ pid; a meno che ($ pid) {$ pty->make_slave_controlling_terminal (); my $ slave = $ pty->slave (); chiudi $ pty; $ slave->clone_winsize_from (\ * STDIN); open (STDIN, "<&". $ slave->fileno ()) o die "Impossibile riaprire STDIN per la lettura, $! \ n"; open (STDOUT, ">&". $ slave->fileno ()) o die "Impossibile riaprire STDOUT in scrittura, $! \ n"; open (STDERR, ">&". $ slave->fileno ()) o die "Impossibile riaprire STDERR in scrittura, $! \ n"; chiudi $ slave; exec (@ARGV); die "Cannot exec (@ARGV): $!";} $ pty->close_slave (); $ SIG {WINCH} = sub {$ pty->slave->clone_winsize_from (\ * STDIN);}; my $ old = IO :: Stty :: stty (\ * STDIN, '-g'); IO :: Stty :: stty (\ * STDIN, 'raw', '-echo'); $ tty = fileno ($ pty); my ($ rin , $ ein) = ('', '', ''); vec ($ rin, 0, 1) = 1; vec ($ rin, $ tty, 1) = 1; vec ($ ein, $ tty, 1 ) = 1; my ($ to_stdout, $ to_tty) = ('', ''); my $ eof; $ SIG {CHLD} = sub {$ eof = 1}; until ($ eof && $ to_stdout eq '' && $ to_tty eq '') {my ($ rout, $ wout, $ eout, $ timeleft); la mia $ vittoria = ''; vec ($ win, 0, 1) = 1 if ($ to_stdout ne ""); vec ($ win, $ tty, 1) = 1 if ($ to_tty ne ""); ($ nfound, $ timeleft) = seleziona ($ rout = $ rin, $ wout = $ win, $ eout = $ ein, undef); if ($ nfound > 0) {if (vec ($ eout, $ tty, 1)) {print STDERR "Eccezione su $ tty \ n"; } if (vec ($ rout, 0, 1)) {my $ buf; if (sysread (STDIN, $ buf, 4096)) {if ($ buf = ~ /.[\0-\037\177”/ || $ buf = ~ / ^ (?: [\ 0- \ 032 \ 034 - \ 037] | \ 033. *? [~ A-zA-NP-Z]) ./) {$ buf = ~ s / [\ 0- \ 037 \ 177] / \ 026 $ & / g; # TODO: aggiungi la sanificazione UTF-8 $ buf = ~ y / \ r / \ n /; } $ to_tty. = $ buf; } altro {$ eof = 1; vec ($ rin, 0, 1) = 0; }} if (vec ($ rout, $ tty, 1)) {my $ buf; if (sysread ($ pty, $ buf, 4096)) {$ to_stdout. = $ buf; } altro {$ eof = 1;
vec ($ rin, $ tty, 1) = 0; $ to_tty = ''; }} if ($ to_tty ne '' && vec ($ wout, $ tty, 1)) {my $ written = syswrite ($ pty, $ to_tty); $ to_tty = substr ($ to_tty, $ scritto) se $ scritto; } if ($ to_stdout ne '' && vec (wout, 1, 1)) {my $ written = syswrite (STDOUT, $ to_stdout); $ to_stdout = substr ($ to_stdout, $ scritto) se $ scritto; }}} END {IO :: Stty :: stty (\ * STDIN, $ old)}
Un approccio migliore sarebbe probabilmente usare un gestore di appunti in cui puoi specificare la modalità di incolla e questo segnalerebbe selezioni potenzialmente pericolose.