48

When pasting in Terminal.app, 00~ is pasted at the start and 01~ at the end. So when I want to paste /some/path, I actually get 00~/some/path01~. Also an audible sound is heard twice, so probably ^G (ASCII BELL) is also inserted at the start and end of the pasted text.

When I paste the same in an editor, this behaviour is not happening (only /some/path gets pasted).

This happens with all text.

When I stop and start Terminal.app, the behaviour also disappears. But after a while, it is back again.

Any ideas as to what this behaviour is causing?

bmike
  • 235,889
doekman
  • 807
  • 1
    One thing that may help with this if it only occurs occasionally is typing reset into your terminal – programs using more advanced terminal features, typically including the likes such as tmux and vim, may not get the chance to reset the bash feature enable-bracketed-paste discussed below. – Landak Sep 19 '22 at 21:02
  • One data point: This happens to me, too, but only in a Terminal window where I've ssh'ed to another machine, and for some reason, something on that machine's (per the answer below, I guess it's bash) sends the sequence to turn this feature on. That machine also turns the feature off when I exit — but not when I use ~^Z to suspend the ssh session. If I use ~^Z to suspend the ssh session, the feature remains on, and programs on my local machine don't understand it, and I have the same problem. – Steve Summit Sep 19 '22 at 23:53
  • @SteveSummit I concur, same exact experience. It's basically by design (turned on and of at "set" reasonable points). So any unexpected thing breaks the model (ssh disconnect, ~^Z, etc.) – James Risner Sep 19 '22 at 23:57

3 Answers3

63

Short answer: Run the command printf '\e[?2004l'. This sends an escape sequence to the terminal that tells it to stop sending bracketed paste sequences.

Other options: In Terminal.app, you can also reset it with Command-Option-R (or Shell menu > Reset). In iTerm2.app, it's Command-R or Session menu > Reset. In either app, this also resets a number of other weird modes it might get into, which can be handy.

You can also mostly eliminate the problem by either switching your interactive shell to zsh, or installing a newer version of bash (at least v5.1) and switching to that. These use and understand bracketed pastes, and also reset it before each command, so it can't get stuck on (well, past the current command anyway).

Long answer: "Bracketed pastes" are a feature that lets the terminal notify the various programs running in the terminal when data is being pasted (as opposed to being typed in like normal). Basically, it sends special "beginning of paste" and "end of paste" escape sequences (\e[200~ and \e[201~ respectively, where \e represents an ASCII escape character). This is so that, for example, the program can treat a pasted multiline document as a single item rather than seeing each line as a separate item. I also have some shell scripts that use it so they can accept a drag-and-dropped item without my having to switch to the terminal window and hit return to indicate the item's complete.

Generally, when a program understands these sequences and wants to receive them, it'll send another escape sequence to the terminal (\e[?2004h) to tell it to start sending them. It should send another sequence to turn them off (\e[?2004l) when it exits, but if fails to do that, gets disconnected without exiting cleanly, or some other program runs inside of it, or... then you get these sequences being sent to a program that has no idea what they are, and just interprets them as gibberish.

zsh and bash v5.1+ use bracketed paste mode themselves, and therefore 1) don't get confused by the escape sequences, and 2) send the sequence to turn bracketed paste off every time you run another program (/command) and the sequence to turn it back on after each program exits, so it's constantly getting reset to the right state.

(The situation with bash is a bit complicated. macOS only includes bash v3.2.57 by default. Support for bracketed paste was added in v4.4 (with readline 7.0), but seems to be off by default until v5.1. So if you install bash v5.1 or later, and use that as your interactive shell, you shouldn't have trouble with this.)

  • 1
    nice! So that is one thing off my plate. I can learn from your research here. – James Risner Sep 19 '22 at 17:23
  • 2
    bash does too, unless you're running an old version or someone has turned it off (readline option enable-bracketed-paste). – hobbs Sep 19 '22 at 19:11
  • @hobbs Unfortunately, macOS only includes bash v3.2.57, and bracketed paste support wasn't added until v4.4 (/readline 7.0) and doesn't seem to be on by default until v5.1. But it's a good point, and I'll add a note to my answer. – Gordon Davisson Sep 19 '22 at 20:40
  • 3
    @GordonDavisson ah yeah, wasn't paying attention to what site I was on. The whole Apple/bash business is very unfortunate. – hobbs Sep 19 '22 at 20:41
  • I'm not going to use zsh, since I'm using bash on Linux as well. I do have bash 5, but I haven't gotten to use it as default shell. For your answer: could you include that Shell > Reset (or alt+cmd+R) also fixes the issue. That is something people can remember ;-) Thanks for the thorough answer. – doekman Sep 20 '22 at 19:59
  • Sub title: MIDI reset, but for the Terminal. – doekman Sep 21 '22 at 11:29
  • Changing the shell doesn't help when you're pasting into other applications. – Barmar Oct 27 '23 at 16:16
  • How does this mode get enabled in the first place, that we need to use Reset to undo it? Is there a way to prevent it? Should I put the printf command in my .profile? – Barmar Oct 27 '23 at 16:19
  • @Barmar It gets enabled because some program wanted to receive bracketed pastes, so it sent the enable sequence, but for some reason didn't turn it off afterward. Disabling it in .profile wouldn't help because it hasn't been enabled yet when that runs. If it happens repeatedly, you need to figure out what keeps enabling it and failing to disable it when it's done. – Gordon Davisson Oct 27 '23 at 17:47
  • I figured it out. I had ssh'ed to a Linux server running a version of bash that enables it. If I logout cleanly it disables it, but if I get disconnected it never cleans up. Since I usually use a wrapper script to connect to our servers, I can add the disable sequence to the wrapper. – Barmar Oct 27 '23 at 19:01
  • @Barmar Changing your local shell to one that uses bracket pastes would also solve this, because when ssh exits the local shell will send the enable sequence, accept your next command, then send the disable sequence before running that next command. – Gordon Davisson Oct 27 '23 at 20:36
  • @GordonDavisson My solution seems easier than switching to zsh.... – Barmar Oct 27 '23 at 20:38
7

This is technically a feature.

Modern terminals (Terminal.app, iTerm2.app) keep track of your output. For example if you type a 200 character command into a shell, it knows that is one "line". Should you copy it, there is an attempt to maintain that as one line with no additional newlines (\n) in the middle.

iTerm2 has a FAQ on this subject under this question:

"Q: When I paste I get funny characters before and after the pasted text, like 0~ and 1~."

You see the extra characters bracketing pastes when the terminal and the remote site get out of sync with each other. This most commonly happens when you lose your ssh connection or when the editor crashes. Resetting the terminal app can turn paste bracketing off again.

I'm often reminded of the good old days when this feature wasn't turned on. But it also had it's issues with extra newlines in pastes and indention issues.

2

For me, I just reset the terminal:

reset

and the "Ctrl+V" chars are gone.

Glorfindel
  • 4,057
AhmFM
  • 121