zsh-users
 help / color / mirror / code / Atom feed
* bracketed paste mode in xterm and urxvt
@ 2011-05-22 19:16 Mikael Magnusson
  2015-05-28 11:42 ` Jérémie Roquet
  0 siblings, 1 reply; 13+ messages in thread
From: Mikael Magnusson @ 2011-05-22 19:16 UTC (permalink / raw)
  To: Zsh Users

# create a new keymap to use while pasting
bindkey -N paste
# make everything in this keymap call our custom widget
bindkey -R -M paste "^@"-"\M-^?" paste-insert
# these are the codes sent around the pasted text in bracketed
# paste mode.
# do the first one with both -M viins and -M vicmd in vi mode
bindkey '^[[200~' _start_paste
bindkey -M paste '^[[201~' _end_paste
# insert newlines rather than carriage returns when pasting newlines
bindkey -M paste -s '^M' '^J'

zle -N _start_paste
zle -N _end_paste
zle -N paste-insert _paste_insert

# switch the active keymap to paste mode
function _start_paste() {
  bindkey -A paste main
}

# go back to our normal keymap, and insert all the pasted text in the
# command line. this has the nice effect of making the whole paste be
# a single undo/redo event.
function _end_paste() {
#use bindkey -v here with vi mode probably. maybe you want to track
#if you were in ins or cmd mode and restore the right one.
  bindkey -e
  LBUFFER+=$_paste_content
  unset _paste_content
}

function _paste_insert() {
  _paste_content+=$KEYS
}

function _zle_line_init() {
  # Tell terminal to send escape codes around pastes.
  [[ $TERM == rxvt-unicode || $TERM == xterm ]] && printf '\e[?2004h'
}

function _zle_line_finish() {
  # Tell it to stop when we leave zle, so pasting in other programs
  # doesn't get the ^[[200~ codes around the pasted text.
  [[ $TERM == rxvt-unicode || $TERM == xterm ]] && printf '\e[?2004l'
}

Alternatively, you can also do stuff to the text before inserting it,
I have this additional stuff which lets me toggle a mode where all the
pasted text is automatically quoted and a space is appended, which is
useful when pasting (some) urls with ? and & and what have you.

function _end_paste() {
  bindkey -e
  if [[ $_SPACE_AFTER_PASTE_QUOTE = 1 ]]; then
    LBUFFER+=${(q)_paste_content}' '
  else
    LBUFFER+=$_paste_content
  fi
  unset _paste_content
}

function _spaceafterpastequote() {
  if [[ $_SPACE_AFTER_PASTE_QUOTE = 1 ]]; then
    _SPACE_AFTER_PASTE_QUOTE=0
    zle -M "Not inserting a space after pastes, not quoting"
  else
    _SPACE_AFTER_PASTE_QUOTE=1
    zle -M "Inserting a space after pastes and quoting"
  fi
}
zle -N _spaceafterpastequote
# this is a custom wrapper that uses zkbd stuff, just use regular bindkey.
zbindkey Control-Insert _spaceafterpastequote

-- 
Mikael Magnusson


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: bracketed paste mode in xterm and urxvt
  2011-05-22 19:16 bracketed paste mode in xterm and urxvt Mikael Magnusson
@ 2015-05-28 11:42 ` Jérémie Roquet
  2015-05-28 19:16   ` Yuri D'Elia
  2015-05-28 20:30   ` Daniel Hahler
  0 siblings, 2 replies; 13+ messages in thread
From: Jérémie Roquet @ 2015-05-28 11:42 UTC (permalink / raw)
  To: Mikael Magnusson; +Cc: Zsh Users

Hi everyone,

I've kept this mail in my inbox for almost exactly four years (!), as
a cool thing to look at when I'd have time. Obvious, I haven't had
that much time since then, and I've only tested it today… What a
mistake! This is with no doubt one of the most useful additions I've
done to my config in years.

Thanks Mikael!

PS: below is the full quote of the original mail, which could be
useful for people that weren't on this list four years ago. Or for
people like me who didn't give it the attention it deserves.
PS2: I've added screen-256color to my list of supported terminals,
though technically I'm not sure it supports bracketed paste (and I'm
running tmux anyway).

---------- Forwarded message ----------
From: Mikael Magnusson <mikachu@gmail.com>
Date: 2011-05-22 21:16 GMT+02:00
Subject: bracketed paste mode in xterm and urxvt
To: Zsh Users <zsh-users@zsh.org>

# create a new keymap to use while pasting
bindkey -N paste
# make everything in this keymap call our custom widget
bindkey -R -M paste "^@"-"\M-^?" paste-insert
# these are the codes sent around the pasted text in bracketed
# paste mode.
# do the first one with both -M viins and -M vicmd in vi mode
bindkey '^[[200~' _start_paste
bindkey -M paste '^[[201~' _end_paste
# insert newlines rather than carriage returns when pasting newlines
bindkey -M paste -s '^M' '^J'

zle -N _start_paste
zle -N _end_paste
zle -N paste-insert _paste_insert

# switch the active keymap to paste mode
function _start_paste() {
  bindkey -A paste main
}

# go back to our normal keymap, and insert all the pasted text in the
# command line. this has the nice effect of making the whole paste be
# a single undo/redo event.
function _end_paste() {
#use bindkey -v here with vi mode probably. maybe you want to track
#if you were in ins or cmd mode and restore the right one.
  bindkey -e
  LBUFFER+=$_paste_content
  unset _paste_content
}

function _paste_insert() {
  _paste_content+=$KEYS
}

function _zle_line_init() {
  # Tell terminal to send escape codes around pastes.
  [[ $TERM == rxvt-unicode || $TERM == xterm ]] && printf '\e[?2004h'
}

function _zle_line_finish() {
  # Tell it to stop when we leave zle, so pasting in other programs
  # doesn't get the ^[[200~ codes around the pasted text.
  [[ $TERM == rxvt-unicode || $TERM == xterm ]] && printf '\e[?2004l'
}

Alternatively, you can also do stuff to the text before inserting it,
I have this additional stuff which lets me toggle a mode where all the
pasted text is automatically quoted and a space is appended, which is
useful when pasting (some) urls with ? and & and what have you.

function _end_paste() {
  bindkey -e
  if [[ $_SPACE_AFTER_PASTE_QUOTE = 1 ]]; then
    LBUFFER+=${(q)_paste_content}' '
  else
    LBUFFER+=$_paste_content
  fi
  unset _paste_content
}

function _spaceafterpastequote() {
  if [[ $_SPACE_AFTER_PASTE_QUOTE = 1 ]]; then
    _SPACE_AFTER_PASTE_QUOTE=0
    zle -M "Not inserting a space after pastes, not quoting"
  else
    _SPACE_AFTER_PASTE_QUOTE=1
    zle -M "Inserting a space after pastes and quoting"
  fi
}
zle -N _spaceafterpastequote
# this is a custom wrapper that uses zkbd stuff, just use regular bindkey.
zbindkey Control-Insert _spaceafterpastequote


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: bracketed paste mode in xterm and urxvt
  2015-05-28 11:42 ` Jérémie Roquet
@ 2015-05-28 19:16   ` Yuri D'Elia
  2015-05-28 20:30   ` Daniel Hahler
  1 sibling, 0 replies; 13+ messages in thread
From: Yuri D'Elia @ 2015-05-28 19:16 UTC (permalink / raw)
  To: zsh-users

On 05/28/2015 01:42 PM, Jérémie Roquet wrote:
> PS: below is the full quote of the original mail, which could be
> useful for people that weren't on this list four years ago. Or for
> people like me who didn't give it the attention it deserves.
> PS2: I've added screen-256color to my list of supported terminals,
> though technically I'm not sure it supports bracketed paste (and I'm
> running tmux anyway).

Awesomeness. But I didn't like the quoting toggle.
What about these few changes:

function _start_quoted_paste() {
  _paste_quoted=1
  bindkey -A paste main
}

function _start_paste() {
  _paste_quoted=0
  bindkey -A paste main
}

function _end_paste() {
  bindkey -e
  [[ $_paste_quoted == 1 ]] && LBUFFER+=${(q)_paste_content} ||
LBUFFER+=$_paste_content
  unset _paste_content _paste_quoted
}

and now:

bindkey '^x^[[200~' _start_quoted_paste
bindkey '^[[200~' _start_paste

so regular paste is unquoted, but ^x before the paste and it will be
quoted for you. ^x is already a prefix key for me.



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: bracketed paste mode in xterm and urxvt
  2015-05-28 11:42 ` Jérémie Roquet
  2015-05-28 19:16   ` Yuri D'Elia
@ 2015-05-28 20:30   ` Daniel Hahler
  2015-05-28 22:30     ` Bart Schaefer
  2015-05-29 10:00     ` Yuri D'Elia
  1 sibling, 2 replies; 13+ messages in thread
From: Daniel Hahler @ 2015-05-28 20:30 UTC (permalink / raw)
  To: zsh-users

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 28.05.2015 13:42, Jérémie Roquet wrote:

> This is with no doubt one of the most useful additions I've
> done to my config in years.

I've stumbled upon it recently, too, and noticed that the handling of
zle-line-init and zle-line-finish should be improved to not overwrite
an already defined function.

I am using the following pattern to add additional code to these hooks:

  eval "zle-line-init()   { something_new; $functions[zle-line-init]; }"
  eval "zle-line-finish() { something_new; $functions[zle-line-finish]; }"

Does this make sense?
Would this be something that add-zsh-hook could provide?

Apart from that I think that this (bracketed paste mode) should be
included in Zsh's and get maintained this way.  Then it could also be
adjusted for vi-mode.

A variant of this is included in oh-my-zsh, too:
https://github.com/robbyrussell/oh-my-zsh/blob/master/plugins/safe-paste/safe-paste.plugin.zsh


Regards,
Daniel.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2

iD8DBQFVZ3r1fAK/hT/mPgARAl6LAKCwfEev8BBAv34+07MN4IMu+A4V+gCfT1he
DrAUaMop7PJDOiBNSMSnrQo=
=IswQ
-----END PGP SIGNATURE-----


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: bracketed paste mode in xterm and urxvt
  2015-05-28 20:30   ` Daniel Hahler
@ 2015-05-28 22:30     ` Bart Schaefer
  2015-05-29 10:00     ` Yuri D'Elia
  1 sibling, 0 replies; 13+ messages in thread
From: Bart Schaefer @ 2015-05-28 22:30 UTC (permalink / raw)
  To: zsh-users

On May 28, 10:30pm, Daniel Hahler wrote:
}
} I've stumbled upon it recently, too, and noticed that the handling of
} zle-line-init and zle-line-finish should be improved to not overwrite
} an already defined function.
} 
} I am using the following pattern to add additional code to these hooks:
} 
}   eval "zle-line-init()   { something_new; $functions[zle-line-init]; }"
}   eval "zle-line-finish() { something_new; $functions[zle-line-finish]; }"
} 
} Does this make sense?

Mostly; in some obscure cases (e.g., zle-line-init is an autoload and has
not yet been loaded) it could break.

} Would this be something that add-zsh-hook could provide?

Possibly, though it would require its own separate conditional branch
because zle-line-init is not the same flavor of "hook" as everything else.

One way to do this is something like so:

    zle-line-init() {
      local w
      for w in "${(@ok)widgets%zle-line-init-*}"
      do zle $w "$@"
      done
    }

Then you just create widgets named zle-line-init-N where N represents
the order you want them to execute.  Similarly for zle-line-finish.


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: bracketed paste mode in xterm and urxvt
  2015-05-28 20:30   ` Daniel Hahler
  2015-05-28 22:30     ` Bart Schaefer
@ 2015-05-29 10:00     ` Yuri D'Elia
  2015-06-03  8:35       ` Jesper Nygårds
  1 sibling, 1 reply; 13+ messages in thread
From: Yuri D'Elia @ 2015-05-29 10:00 UTC (permalink / raw)
  To: zsh-users

On 05/28/2015 10:30 PM, Daniel Hahler wrote:
> Apart from that I think that this (bracketed paste mode) should be
> included in Zsh's and get maintained this way.  Then it could also be
> adjusted for vi-mode.

I do agree that mainlining this would make a lot of sense, even as a
setopt. Or at least provide the keymap/functions needed to enable it.


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: bracketed paste mode in xterm and urxvt
  2015-05-29 10:00     ` Yuri D'Elia
@ 2015-06-03  8:35       ` Jesper Nygårds
  2015-06-03  8:48         ` toki clover
  2015-06-03 10:04         ` Yuri D'Elia
  0 siblings, 2 replies; 13+ messages in thread
From: Jesper Nygårds @ 2015-06-03  8:35 UTC (permalink / raw)
  To: Zsh Users

[-- Attachment #1: Type: text/plain, Size: 570 bytes --]

I have a hard time figuring out how this is useful. Could you guys post
some examples of what you are using this function for?


On Fri, May 29, 2015 at 12:00 PM, Yuri D'Elia <wavexx@thregr.org> wrote:

> On 05/28/2015 10:30 PM, Daniel Hahler wrote:
> > Apart from that I think that this (bracketed paste mode) should be
> > included in Zsh's and get maintained this way.  Then it could also be
> > adjusted for vi-mode.
>
> I do agree that mainlining this would make a lot of sense, even as a
> setopt. Or at least provide the keymap/functions needed to enable it.
>
>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: bracketed paste mode in xterm and urxvt
  2015-06-03  8:35       ` Jesper Nygårds
@ 2015-06-03  8:48         ` toki clover
  2015-06-03 10:04         ` Yuri D'Elia
  1 sibling, 0 replies; 13+ messages in thread
From: toki clover @ 2015-06-03  8:48 UTC (permalink / raw)
  To: Jesper Nygårds; +Cc: Zsh Users

[-- Attachment #1: Type: text/plain, Size: 548 bytes --]

2015-06-03 10:35 GMT+02:00 Jesper Nygårds <jesper.nygards@gmail.com>:

> I have a hard time figuring out how this is useful. Could you guys post
> some examples of what you are using this function for?
>
>
Copy/past obviously! Well, I did not figured the "bracketed" part either
after looking for... and ending to:

http://invisible-island.net/xterm/ctlseqs/ctlseqs.html

because the old reference is broken.
There is a section on that XTerm page... but it does not help much.

-- 
Error 404: gentoo user <0123456789> was not found

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: bracketed paste mode in xterm and urxvt
  2015-06-03  8:35       ` Jesper Nygårds
  2015-06-03  8:48         ` toki clover
@ 2015-06-03 10:04         ` Yuri D'Elia
  2015-06-03 10:14           ` Jesper Nygårds
  2015-06-03 12:06           ` Mikael Magnusson
  1 sibling, 2 replies; 13+ messages in thread
From: Yuri D'Elia @ 2015-06-03 10:04 UTC (permalink / raw)
  To: zsh-users

On 06/03/2015 10:35 AM, Jesper Nygårds wrote:
> I have a hard time figuring out how this is useful. Could you guys post
> some examples of what you are using this function for?

Bracketed paste is of course useful for copy/paste in the terminal.

When pasting in a terminal, normally the shell receives the raw input,
including newlines, quotes and the like. There's no difference between
typing and pasting. For example, often you want to select a code snippet
from a web page, and the page might include extra markup that breaks the
command and/or runs it directly even when you're careful.

Besides being dangerous, it's also annoying that you need to quote the
pasted text manually. For example

wget <paste url>

will often fail if the url contains ?. You need to edit the command and
quote it. Annoying.

Bracketed paste is implemented by the terminal+shell: the terminal sends
control sequences during paste that allow the shell to know that
something is being paste as opposed to being typed. The shell can then
act accordingly.

In the 'safe-paste' oh-my-zsh plugin, the pasted text is not directly
executed: the newlines are inserted as a multi-line command instead,
which allow you to see the command before executing it instead.

In the posted examples, you can actually chose if the pasted text should
be literal or quoted. With quoted paste, you can pass urls and similar
blocks of text as command arguments without having to fudge it.


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: bracketed paste mode in xterm and urxvt
  2015-06-03 10:04         ` Yuri D'Elia
@ 2015-06-03 10:14           ` Jesper Nygårds
  2015-06-03 12:06           ` Mikael Magnusson
  1 sibling, 0 replies; 13+ messages in thread
From: Jesper Nygårds @ 2015-06-03 10:14 UTC (permalink / raw)
  To: Zsh Users

[-- Attachment #1: Type: text/plain, Size: 1780 bytes --]

OK, I see. I already use url-quote-magic for pasting urls, but I can see
the advantage of also being able to edit the paste before it's really
inserted.


On Wed, Jun 3, 2015 at 12:04 PM, Yuri D'Elia <wavexx@thregr.org> wrote:

> On 06/03/2015 10:35 AM, Jesper Nygårds wrote:
> > I have a hard time figuring out how this is useful. Could you guys post
> > some examples of what you are using this function for?
>
> Bracketed paste is of course useful for copy/paste in the terminal.
>
> When pasting in a terminal, normally the shell receives the raw input,
> including newlines, quotes and the like. There's no difference between
> typing and pasting. For example, often you want to select a code snippet
> from a web page, and the page might include extra markup that breaks the
> command and/or runs it directly even when you're careful.
>
> Besides being dangerous, it's also annoying that you need to quote the
> pasted text manually. For example
>
> wget <paste url>
>
> will often fail if the url contains ?. You need to edit the command and
> quote it. Annoying.
>
> Bracketed paste is implemented by the terminal+shell: the terminal sends
> control sequences during paste that allow the shell to know that
> something is being paste as opposed to being typed. The shell can then
> act accordingly.
>
> In the 'safe-paste' oh-my-zsh plugin, the pasted text is not directly
> executed: the newlines are inserted as a multi-line command instead,
> which allow you to see the command before executing it instead.
>
> In the posted examples, you can actually chose if the pasted text should
> be literal or quoted. With quoted paste, you can pass urls and similar
> blocks of text as command arguments without having to fudge it.
>
>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: bracketed paste mode in xterm and urxvt
  2015-06-03 10:04         ` Yuri D'Elia
  2015-06-03 10:14           ` Jesper Nygårds
@ 2015-06-03 12:06           ` Mikael Magnusson
  2015-06-03 14:01             ` Yuri D'Elia
  1 sibling, 1 reply; 13+ messages in thread
From: Mikael Magnusson @ 2015-06-03 12:06 UTC (permalink / raw)
  To: Yuri D'Elia; +Cc: Zsh Users

On Wed, Jun 3, 2015 at 12:04 PM, Yuri D'Elia <wavexx@thregr.org> wrote:
> On 06/03/2015 10:35 AM, Jesper Nygårds wrote:
>> I have a hard time figuring out how this is useful. Could you guys post
>> some examples of what you are using this function for?

It also makes every paste a single undo/redo point.

> Bracketed paste is of course useful for copy/paste in the terminal.
>
> In the 'safe-paste' oh-my-zsh plugin, the pasted text is not directly
> executed: the newlines are inserted as a multi-line command instead,
> which allow you to see the command before executing it instead.

It's probably worth noting that 'safe-paste' is a bad name for this,
since the pasted text can include the end-paste escape code, causing
the rest of the paste to appear to the shell as typed by the user.

This page has an example attack against the plugin,
https://thejh.net/misc/website-terminal-copy-paste

Hm, seems newer xterm prohibits pasting raw escape codes, so if you
have one of those versions, you are safe.

-- 
Mikael Magnusson


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: bracketed paste mode in xterm and urxvt
  2015-06-03 12:06           ` Mikael Magnusson
@ 2015-06-03 14:01             ` Yuri D'Elia
  2015-06-06  8:51               ` toki clover
  0 siblings, 1 reply; 13+ messages in thread
From: Yuri D'Elia @ 2015-06-03 14:01 UTC (permalink / raw)
  To: zsh-users

On 06/03/2015 02:06 PM, Mikael Magnusson wrote:
> It's probably worth noting that 'safe-paste' is a bad name for this,
> since the pasted text can include the end-paste escape code, causing
> the rest of the paste to appear to the shell as typed by the user.
> 
> This page has an example attack against the plugin,
> https://thejh.net/misc/website-terminal-copy-paste
> 
> Hm, seems newer xterm prohibits pasting raw escape codes, so if you
> have one of those versions, you are safe.

Not urxvt though. I just submitted a patch:

https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=787628



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: bracketed paste mode in xterm and urxvt
  2015-06-03 14:01             ` Yuri D'Elia
@ 2015-06-06  8:51               ` toki clover
  0 siblings, 0 replies; 13+ messages in thread
From: toki clover @ 2015-06-06  8:51 UTC (permalink / raw)
  To: Yuri D'Elia; +Cc: Zsh Users

[-- Attachment #1: Type: text/plain, Size: 210 bytes --]

I've just pushed a commit in dotfiles[1] repository with this
and adding: restore previous keymap and a clean up.

[1]:
https://raw.githubusercontent.com/tokiclover/dotfiles/master/.zsh/lib/bracketed-paste.zsh

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2015-06-06  8:51 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-05-22 19:16 bracketed paste mode in xterm and urxvt Mikael Magnusson
2015-05-28 11:42 ` Jérémie Roquet
2015-05-28 19:16   ` Yuri D'Elia
2015-05-28 20:30   ` Daniel Hahler
2015-05-28 22:30     ` Bart Schaefer
2015-05-29 10:00     ` Yuri D'Elia
2015-06-03  8:35       ` Jesper Nygårds
2015-06-03  8:48         ` toki clover
2015-06-03 10:04         ` Yuri D'Elia
2015-06-03 10:14           ` Jesper Nygårds
2015-06-03 12:06           ` Mikael Magnusson
2015-06-03 14:01             ` Yuri D'Elia
2015-06-06  8:51               ` toki clover

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).