Pasting long lines into Mac OS X Terminal - macos

When I paste a long string (ie, more characters than the width of the terminal window), the terminal doesn't autoscroll and put them in multiple lines.
Instead, it basically wraps onto the same line. In other words, it prints until the end of the current line and then starts printing over the existing characters from the beginning of the same line...
Here's a screenshot. Notice the characters "789abc..." at the beginning of the line.
I'm on 10.8.3 with Terminal 2.3. $TERM is xterm-256color.
A colleague has the exact same machine setup (though different Terminal colors and probably other configs) and he can get it to scroll.
Any ideas?
Thanks!

It sounds like you don't have the nonprinting parts of your PS1 prompt string properly marked. The nonprinting parts (e.g. color change escape sequences) -- and only the nonprinting parts -- need to be marked with \[ ... \] so that the shell can tell they don't take up space on screen (and hence can tell where to wrap). For example, my prompt string is \[\e[0;32m\]\h\[\e[m\]:\W \[\e[0;34m\]\u\[\e[m\]$, which parses out as:
\[\e[0;32m\] - change color to green type (nonprinting, so it's wrapped in \[ ... \])
\h - the hostname (printing)
\[\e[m\] - normal print (no color) (nonprinting, hence wrapped)
:\W - the current directory (and delimiters) (printing)
\[\e[0;34m\] - change to blue type (nonprinting)
\u - the hostname (printing)
\[\e[m\] - normal type (nonprinting)
$ - final delimiter before the actual command

Related

How can I properly use two-character-width emoji in my bash prompt?

I want to use an American flag emoji in my bash prompt (i.e. PS1 environment variable). However, the American flag emoji causes the terminal cursor to offset an extra character to the right.
πŸ‡ΊπŸ‡Έ is comprised of two unicode characters, πŸ‡Ί and πŸ‡Έ. I believe terminal is converting this to a mono-spaced emoji character (the flag), yet still allocating space for two characters. How can I achieve my expected cursor position?
I want:
πŸ‡ΊπŸ‡Έ Desktop akirna πŸ—½ ls|
I get:
πŸ‡ΊπŸ‡Έ Desktop akirna πŸ—½ ls | << weird space offset before cursor
My ~/.bash_profile is:
export PS1='πŸ‡ΊπŸ‡Έ \W \u πŸ—½ '
Updated Answer
The way your are setting the prompt is not evaluating the escape characters. Add a $ before the string to make it evaluate the escape codes:
pompt$ export PS1='XY \x08: '
XY \x08: echo "Well that didn't work..."
Should become:
pompt$ export PS1=$'XY \x08: '
XY: echo "Escape code success!"
(See Charles Duffy's comment on this answer for why I removed export.)
The example above sets the prompt to the characters X, Y, [space], [backspace], [colon] resulting in a displayed prompt of just "XY:".
On my system, the flag is rendered as two characters (πŸ‡Ί and πŸ‡Έ), so I cannot verify this, but I think adding a backspace (\x08) should work for you:
PS1=$'πŸ‡ΊπŸ‡Έ \\W \\u πŸ—½\x08'
Notes about edits
My original answer suggested using a sub-shell as follows:
export PS1=$(printf "XY \x08")
Many thanks to Charles Duffy for his input~
I worked around this by converting the character to hex, and then putting zero width markers around the second part of the character
so for πŸ‡ΊπŸ‡Έ we get
PS1='\xf0\x9f\x87\xba\[\xf0\x9f\x87\xb8\] '

Trouble understanding a bash command

I'm trying to set up a program and came across this line in a bash script. Could someone tell me what it does? I'm not very experienced with bash.
export PS1='\e[0;33mmyProject \e[0;32m\[\e]0;\u#\h: \w\a\]${debian_chroot:+($debian_chroot)}\u#\h:\w\$\e[0m '
Thank you very much!
This command does two things. It sets the title of the terminal window, and
sets the bash prompt.
export PS1='\e[0;33mmyProject \e[0;32m\[\e]0;\u#\h: \w\a\]${debian_chroot:+($debian_chroot)}\u#\h:\w\$\e[0m '
Piece by piece:
export PS1=
This sets the PS1 variable, which is contains the bash prompt.
\e[0;33m
\e is translated to the ESC character (ascii=0x1B), which is a Control Sequence Introducer, which signifies the beginning of an ANSI Escape Code. The m character at the end of the sequence indicates that the everything between [ and m is to be interpreted as a ;-separated list of SGR (Select Graphic Rendition) parameters (See here for more information). The 0 clears all previous text formatting, and the 33 sets the text color to yellow.
myProject
This just adds the string myProject to the bash prompt.
\e[0;32m
This clears all the previous text formatting (0) and sets the text color to green. (32)
\[ ... \]
\[ begins a sequence of non-printing characters which ends with \]. Everything between those two delimiters will not be visible in the prompt.
\e]0;\u#\h: \w\a
This sets the title of the terminal window to something like
username#hostname: /current/working/directory
The next bit:
${debian_chroot:+($debian_chroot)}
If the variable $debian_chroot has been defined, then this expression will evaluate to the value of $debian_chroot.
$debian_chroot is a variable that is set in /etc/bash.bashrc. This post explains it a lot better than I can.
\u#\h:\w\$\e[0m
\u evaluates to the username of the current user, \h evaluates to the name of the computer, and \w evaluates to the current working directory. \$ is just the character $. It needs to be escaped because in bash script, the character $ signifies that the following characters are the name of a variable. \e[0m reverts the text formatting back to default.
An image of what the prompt might look like in a terminal:
This is quite a complicated command you have here!
Let's break it down section by section.
export
This means that we are setting a variable to be used in other programs.
PS1=
The name of the variable is PS1.
\e
This is an escaped character. In bash (and most programming languages), Everything with a backslash before it is an escaped character. It is used for when you need to include a control character like a space, or the control key itself in a string. When it's escaped, bash treats it like it's part of the string, and not another control character.
[
This is the start of an array. It's very similar to an array in a C program.
;
This is an end character, it can mean several different things. Here, it's being used to define part of the array.
There is some other stuff here, but it's mostly just data in the array.
:
This is a NOT operand. It is used to determine the inverse of something.
${debian_chroot:+($debian_chroot)}
This is a variable. In bash, variables start with a $.
It is using the variable debian_chroot and adding it to itself if it's not null.
This command is just defining a variable, in this case an array containing information probably about a chroot with a debian install in it.

How to move right or left by 'x' characters in Bash?

In bash sometimes I have very long commands where I need to edit some words. Right now I use End/Home to move end/start of the command, but what if I have to move say x characters in a line?
I need something like xb/xw of VI, but instead of words I need to move characters.
What about ditching emacs mode and switching to vi mode editing?
set -o vi
and you have all the power of vi-like command line editing, like 3l to go left three characters and 5B to go back 5 words. The Pos 1 key then becomes 0 and End becomes $.
In emacs mode, you can use Meta3Controlb to move back 3 characters, and Meta3Controlf to move forward 3 characters. For multi digit counts, you need to precede each digit with the Meta key (e.g., to move 10 characters back, Meta1Meta0Controlb).
Meta is usually the Alt key, but may be the Esc key instead (on Mac OS X, for instance).
(Yes, vi-command mode makes it easier.)
There is a command, universal-argument, that allows you to type all the digits at once, but it is unbound by default. Bind it with, say,
bind "\C-a":universal-argument
then typing Control-a will enter you into an "argument" mode, prefixing the current line (arg: 4), and allowing you to type digits to change the argument used by the next non-digit character you type. (See universal-argument in the bash man page for the full details.)
You could use the command as below
Command:
cp some_file1 some_file2 some_file3 /root/Desktop
After executing the command do the following
^some_file2^some_file4
and it will execute the command
cp some_file1 some_file4 some_file3 /root/Desktop ;
What happened is the some_file2 is replaced by some_file4 and the command is executed

Issue with encoding of a character (not able to sed or .gsub)

I am dealing with some multilingual data(English and Arabic) in a json file with a weird character i am not able to parse. I am not sure what the character is. I tried getting the ASCII value via vim and this is what i got
"38 0x26"
This is the status line in vim i used to get the value (http://vim.wikia.com/wiki/Showing_the_ASCII_value_of_the_current_character).
:set statusline=%<%f%h%m%r%=%b\ 0x%B\ \ %l,%c%V\ %P
This is how the character looks in vim -
I tried 'sed' and '.gsub' to replace this character unsuccessfully.
Is there a way where i can replace this character(preferably with .gsub ruby) with '&' or something else?
Thanks
try with something like
sed 's/[[:alpnum:][:space:]\[\]{}()\.\*\\\/_(AllAsciiVariationYouWant)/&/g;t
s/./?/g' YourFile
where (AllAsciiVariationYouWant) is all character that you want to keep as is (without the surrounding "()" )
JSON is encoded in UTF-8 (Unicode). If you're seeing funky-looking characters in your file, it's probably because your editor is not treating Unicode characters properly. That could be caused by the use of a terminal emulator that doesn't support Unicode; an incorrect $LANG setting; vim not being able to correctly determine the encoding of the file; and likely other reasons.
What terminal program are you using? What's your $LANG environment variable set to (echo $LANG)? If you're certain your terminal supports Unicode, try:
LANG=en_US.utf-8 vim your_file_here.json
(The above example assumes that U.S. English is appropriate for the file, which it may not be.)
As for replacing characters in the file, vim's substitution command can be used:
:%s/old text/new text/g
The above command will run the substitute command on all lines in the file (%), replacing every instance of "old text" with "new text". (The g at the end tells vim to replace every instance on a line, not just the first it finds.)

Putty: copy & paste -> preserve blanks

we want to switch to Putty at work, but we have one big problem: in error situations we have to copy some lines from our logfile (using less/vi and mouse copy & paste). These lines can be 32 KB long and contain several blanks, the blanks need to be preserved. Unfortunately, if the copied content is wrapped because it doesn't fit in one line in the window, Putty seems to replace the trailing blanks with a newline character.
e.g. if we have the line (with trailing spaces that need to be preserved -> you see the trailing spaces if you select the example):
LINE START, WINDOW IS 80 CHARACTERS WIDTH, BUT LINE IS 32KB
SO LINE IS WRAPPED IN THE PUTTY WINDOW
THE TRAILING SPACES NEED TO BE PRESERVED....
BUT USING PUTTYS COPY & PASTE, PUTTY REPLACES SPACE CHARACTERS BY NEWLINE
...LINE END
and we copy & paste, we get (select second example):
LINE START, WINDOW IS 80 CHARACTERS WIDTH, BUT LINE IS 32KB
SO LINE IS WRAPPED IN THE PUTTY WINDOW
THE TRAILING SPACES NEED TO BE PRESERVED....
BUT USING PUTTYS COPY & PASTE, PUTTY REPLACES SPACE CHARACTERS BY NEWLINE
...LINE END
Putty cuts the trailing spaces and inserts a newline character. Can this behaviour be configured/changed in Putty?
Thank you,
Christian
I have used non-breaking spaces to retain trailing whitespace when copying/pasting from PuTTY. My application was ssh-ing into a linux box and copying/pasting some code using the Bourne shell, so I don't know how widely this will work in other environments.
To insert a non-breaking space, hold the Alt key and type 255, then release the Alt key. The following example can be used for testing. For some reason, the code doesn't retain the non-breaking space when I copy/paste directly from this webpage, so you will need to test it this way:
a. Copy/paste the code below into notepad
b. Delete the space in blank=" "
c. Insert a non-breaking space with Alt+255
d. Copy/paste the code into PuTTY
e. Copy/paste the output back into notepad to view results
CODE
# non-breaking space, Alt+255
blank="Β "
# regular space
space=" "
echo "
blank:$blank
space:$space
"
Which outputs a trailing space for the $blank var, but not for the $space var.
OUTPUT
blank:
space:
I'm not sure that Putty can do it but in my case (putty working on redhat open client) I converted source files to unix format (dos2unix command).
Now pasting works fine.

Resources