I'm writing a small program that prints to the terminal its output in tab separated format. But whenever I select the text with tabs and copy it, the tabs are replaces with some number of spaces.
What can I do to make terminal not replace tabs with spaces when trying to copy?
On macOS Sierra (maybe also in earlier versions), you can do:
Edit -> Copy Special -> Copy Plain Text
Or using the shortcut:
alt+shift+⌘ cmd+C
Your best bet may be to substitute "\t" in place of tabs in your output, and do a search and replace after you copy and paste it to the destination.
You could use any character or string as the substitute, of course, but using "\t" makes it easy to restore the tabs using echo -e if pasting to a command-line environment.
The substitution can be done using: |sed 's/\\/\\\\\\/g;s/\t/\\t/g'
I am able to do it on my mac terminal. Here are some good tests:
printf '>\t<\n' : works (copies into sublime as a tab; selecting it only lets me select the full tab not individual spaces)
printf '>\t<\n' | less : fails
printf '>\t<\n' | more : fails
printf '>\t<\n' | less | cat : works (less detects output is file/pipe not terminal so no terminal settings applied)
printf '>\t<\n' | less | cat -vet : outputs ">^I<$" (less detects pipe output so no terminal settings applied)
printf '>\t<\n' | vi - : fails but when I move in vi, it jumps across the tab in 1 keypress so it knows it is a tab
reset : from now on, it always fails
stty -tabs : from now on, it always fails
stty tabs : fixes the reset/stty -tabs problem, now it can work again
One guy got less to work by altering the source: https://unix.stackexchange.com/questions/412060/how-to-get-less-to-show-tabs-as-tabs
less related options: '-U' shows tabs as '^I', '-x4' sets tab size
For git diff:
git diff | head -40 : works (copies into sublime with tabs)
git diff | cat : works
git diff | less : fails (less applies terminal settings)
git diff : fails (my git pager is less)
Related
TL;DR?
How can I change every instance of one character (e.g. 'E') in a terminal window to another string of characters (e.g. '~E'), moving all other characters along in the window in the process? So:
abcdEfghij
becomes:
abcd~Efghij
This should work in the gnome-terminal and work with whatever output is on that terminal, from whatever program. Ideally it will be a script or other program I can run within that terminal emulator.
The context
I am using a Braille display (the Canute 360) with a Braille screen-reader (brltty), which at present does not support capital letters. They show up in Braille the same as lower-case letters. Until this is developed for BRLTTY I sometimes need to be able to force showing which letters are capitalised in order for me to, for example, write code.
The proposed solution
N.B. The below proposed solution is not intended to be elegant; it is a quick and dirty way of letting me and other Braille-using developers continue to program with this display for our work until the proper solution is forthcoming in the screen-reader proper.
I am trying to essentially 'wrap' the output of the terminal emulator (in this case gnome-terminal to force a certain character in front of every capital letter so on the Braille display it can be identified. I am going to assume that character is tilde (~). I am not concerned about this breaking vertical alignment, or forcing the line off the edge of the display. I am assuming a 40 character wide terminal (width of the Canute).
So this normal output:
$ echo ${string}
A Quick Brown Fox
Jumps over the lazy
Dog. Etc.
$
Becomes this:
$ echo ${string}
~A ~Quick ~Brown ~Fox
~Jumps over the lazy
~Dog. ~Etc.
$
That would then be viewable on the Canute (in US Computer Braille) as this:
$ echo ${string}
~a ~quick ~brown ~fox
~jumps over the lazy
~dog. ~etc.
$
It is fine for this to be a command that has to be called first, like screen. So:
$ caps-hack
$ nano
[doing my thing, then quit nano]
$
[ctrl-x to quit caps-hack]
$
Or alternatively it could launch a new terminal window, or it could be tied to specific TUI applications (like nano). I will primarily be using it for working inside vi, nano, micro and other editors, so if it cannot capture all terminal output the solution is still valuable.
Example use case: Micro/nano text editor
When I need to see capitals whilst editing text using micro or nano I would first launch caps-hack, then I could use the TUI editor, exit it, be back on the terminal, then cancel caps-hack if I wanted to revert to usual behaviour.
This is what nano normally looks like:
GNU nano 4.8 New Buffer Modified
This is a nonsense file for
Stackoverflow.
^G Get Hel^O Write O^W Where I^K Cut Tex
^X Exit ^R Read Fi^\ Replace^U Paste T
I'm looking for a solution that would then make it look like this:
~G~N~U nano 4.8 ~New ~Buffer ~Modi
~This is a nonsense file for
~Stackoverflow.
^~G Get ~Hel^~O ~Write ~O^~W ~Where ~I^~
^~X ~Exit ^~R ~Read ~Fi^\ ~Replace^~U
(Note that I have cut it off at 40 characters.)
The effect would be the same (inserting tildes, cutting off at 40 characters) whether I was in the terminal itself, in mc, or watching a ping stream.
This active use case means that so far as I can see I cannot simply pipe the output of programs to a bash script (like the one below), as that wouldn't work with a TUI. So I cannot do: $ nano myfile.txt | caps-hack
What I have tried so far
I have not worked out how to essentially capture the output, modify it and write it back to the terminal window. However I have the following shell snippet which I believe could be used for it, if I know where to put it.
# Repeat for all visible lines in the terminal
moddedline1=$( echo ${originalLine1} | sed -E -e 's/\([A-Z]\)/~\1/g' )
moddedline1="${moddedline1:0:40}"
tput cup 1 0 && printf "${moddedline1}"
Is it possible to have a bash script split the terminal window horizontally at one point, so that the left side details the overall progress of tasks, and the right side contains verbose output from the current task being run?
I've found some people referencing nohup and screen in contexts of splitting the terminal window, but I don't know how to get that going in a bash script sense, or if its even the right direction for my needs.
At the moment, I've got lots of long tasks with long output, so I'm sending the output of each to a cumulative log file, instead of dumping on the screen. Then, as an interim, manually opening a new terminal window to use watch tail LogFile* to keep an eye on what's going on.
It would be great if I could automate that process.
Update
Some leads.
This post and its comments were very helpful, to establish that you can launch a command in one window and send its output to another based on its pts value.
For example, ls > /dev/pts/7 will display output of ls in the terminal window at pts/7.
Still stumped about how to automate splitting the screen programatically, and using that, instead of a new window.
I got a working example going with Terminator.
Start the bash script below in a new Terminator window:
terminator --command="bash /path/to/script"
And once we're running in that, it's a bit of a hack solution, but to split the screen by command-line in the bash script, I ended up using xdotool to send keybindings to Terminator. Like so:
#!/bin/bash
# send keybinding that splits screen vertically
xdotool key Ctrl+Shift+E
# Terminator now sets focus to the right side (the new split) by default, so send keybinding that returns the focus to our left side
# sleep a tiny little bit first
sleep 0.01
xdotool key Alt+Left
# now to send output to the right side, let's work out "where" the ride side is
# use who to find the pts ids of all currently spanwed terminal windows
# use tail to find the last line from who (which we assume is the terminal window we just split)
# then grep to find just the number after pts/
## windowID=$(who | tail -n1 | grep -oP 'pts/\K[0-9]*')
# updated this to fix bug where who does not return pts values
# https://askubuntu.com/questions/1110203
windowID=$(ps -u $USER -o tty | awk 'NR>1 && $1 != "?" {a[$0]++};END{for(val in a) print val}' | tail -n1 | grep -oP 'pts/\K[0-9]*')
# now we can send output from commands to the right side split window by using its pseudo device id. for example:
ls -lah >> /dev/pts/$windowID
exit
Bash provides the feature of colors for specific types of files. For example, by default ls will show directories as blue, utilities as green, files as white and etc. I know these colors can be customized for the output of commands such as ls via modifying ~/.dir_colors and other files depending upon how widespread on the system the change should be applied.
However, during screen-casts and presentations I have seen the command line itself have these color modifications. For example at the bash prompt if someone types a utility and starts typing its arguments, the utility on the line is colored green as it would be in the output of ls. This seems like a nice feature, but all google searches seem to turn up is how to modify outputs of ls and customize the colors, but not how to apply this to the command line itself. How can this be applied to the command line? Is it possible via bash or is this a feature of some terminal software these users are using?
fish - the Friendly interactive shell https://en.wikipedia.org/wiki/Friendly_interactive_shell looks like it reacts as you describe.
Not sure how helpful it will be but the tput command can help with changing the colours and formatting of the command line.
For example, to change the colour of the text in your terminal to red you can do.
tput setaf 1
This accepts numerical arguments between 1 and 7. This could then be added to ~/.bash_profile or ~/.bashrc in order to set the colours at the time of user login or when a new terminal session is started.
Along with changing colours tput has the ability to make the text bold, underlined and more.
For more usage check out these pages:
TDLP - http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x405.html
Hack40- http://linux.101hacks.com/ps1-examples/prompt-color-using-tput/
Oh yeah, I always do this for every Mac and Linux server I have. Not only can you tell it to provide useful info such as "user#server-name: working/directory", but it's just plain fun!
I like to have mine tell me which Git branch I'm working on, when I'm inside a Git repository!
You just have to add one change to your ~/.bash_profile or ~/.bash_rc
Here is a website the will help you generate the complicated code: https://www.kirsle.net/wizards/ps1.html
And just so you have an example, here is what I use on my personal Mac (without the Git branch detection):
PS1='\[\033[02;36m\][\u#MBP:\[\033[02;33m\]\w]\$\[\033[00m\] '
The above code will give you:
A teal color showing your user and a static hostname: "user#MBP". You can rename the hostname to anything you like.
Then, a yellow 'current working directory'
Lastly followed by a '$' symbol and resets the colors back to white
Specifying the colors for different parts gets tricky. I'd definitely recommend using the generator. But if you want to blaze your own trail, here is a list of all the codes for the bash colors: http://blog.bigdinosaur.org/easy-ps1-colors/
To have it set every time you login to your workstation add above export command to your $HOME/.bash_profile file or $HOME/.bashrc file.
vi $HOME/.bashrc
Append the following lines:
export PS1="\[\e[31m\][\[\e[m\]\[\e[38;5;172m\]\u\[\e[m\]#\[\e[38;5;153m\]\h\[\e[m\] \[\e[38;5;214m\]\W\[\e[m\]\[\e[31m\]]\[\e[m\]\\$ "
cat<<'EOF'
_..._
.' '.
/ _ _ \
| (o)_(o) |
\( ) /
//'._.'\ \
// . \ \
|| . \ \
|\ : / |
\ `) ' (` /_
_)``".____,.'"` (_
) )'--'( (
'---` `---`
EOF
Save and close the file in vim/vi.
To get into the ex mode, press [Esc] key and then : (the colon). For example, to exit from vi saving changes, press [Esc], : (colon) and type wq:
:wq
You can also quit, discard all changes by pressing [Esc], : (colon) and q!.
:q!
You need to press [Esc] key followed by the colon (:) before typing the following commands:
| Command | Description |
|------------- |---------------------------------------------------------------- |
| q | Quit |
| q! | Quit without saving changes i.e. discard changes and quit file |
| r fileName | Read data from file called fileName |
| w | Save file and continue editing |
| wq | Write and quit (save and exit) |
| x | Same as wq command i.e. write and quit (save and exit) |
| w fileName | Write to file called fileName (save as) |
| w! fileName | Overwrite to file called fileName (save as forcefully) |
I'm using Bash on Ubuntu, and sometimes when I run a command, the output overfills the terminal, even when I scroll up to the top. How can I access the part of the output that's hidden because of the overfill?
You can try any of the following (Using the ls command as an example for where the commands would go):
Option A: Redirect the output to a file with > and then examine the file later with less or a text editor like vim or gedit.
$ ls > outfile
$ less outfile
$ vim outfile
$ gedit outfile
$ emacs outfile
To write the command's output to both stdout and stderr to your outfile, add a 2>&1 at the end, like so:
$ ls > outfile 2>&1
Option B: pipe the output of your command directly to less
$ ls | less
Note: if you view the output with less with either of the above options, use:
Ctrl+F to go down a page,
Ctrl+B to go up a page ,
Ctrl+D for down 1/2 a page,
Ctrl+U for up 1/2 a page
Arrow keys to move up / down line by line.
Press q to exit from less anytime.
You can pipe the output to less :
command | less
That's actually not bash doing that, it's the terminal program.
You have a couple of options. Perhaps the easiest is just piping your command through less, which allows you to scroll back and forth:
command_with_much_output | less
Secondly, you can configure your terminal program. Assuming you're using the default one, you can open up the Edit menu and select Profile preferences:
Then choose the Scrolling tab and you can change the scrollback buffer size:
Or you can increase the number of lines kept to scrollback in profile's properties (assuming you are using gnome-terminal).
You can try Redirecting the output to a text file .
command > file
When I try to read bash history into vim, I get nothing.
:r !history
If I just execute the command, i.e.
:!history
instead of history I get a snapshot of my terminal as it looked before I started vim.
How can I read the output of "history" into vim? Reading the contents of .bash_history won't do as I save history with timestamps:
HISTTIMEFORMAT='%Y.%m.%d %R '
From a shell prompt:
history | vim -
The problem is that that history is only known by the bash shell that started vim. When you do :!history from within vim, you're starting a new bash shell that has its own history, which is empty, which is why you just see the screen as it looked when you started vim: it's outputting all the lines in its history, which is a grand total of zero. This actually is an oversimplification, but anyway you can't get a history of the commands that you typed just before starting vim this way.
If you want to get those lines of history without exiting vim, you can suspend vim by pressing CTRL-Z and then write the history to a file using history >history.tmp. Then type fg 1 to resume vim: this will tell bash to transfer focus back to its "job number 1", which will normally be vim. The job number is displayed after you hit CTRL-Z:
[1]+ Stopped vim
so if there's a number other than 1 in the brackets, then you should do fg for that number instead. Then (hopefully you know this) when you're back in vim just :tabedit history.tmp, for example, to open the saved history in a new tab.
You'll have timestamps in this output too, but since you're in vim you can easily filter them out with a :substitute command. Alternatively you can cut them out using HISTTIMESTAMP='' history rather than just history when writing to the file; this will still output the index of each entry. I guess you can filter that out on its way into the file too, by piping it through sed or cut or one of their crew. But it's really easy to do this from within vim (assuming you know the basics of regular expressions; if not, start with :help :substitute or maybe look for a regex tutorial).
Note that if you read in the lines from ~/.bash_history, you're only getting the history from bash shells which have completed, ie you typed exit and the terminal window closed. So any commands you typed just before starting vim won't be there. You can change the way this works but then you end up with commands from different sessions all jumbled up together in the history.
:r!echo "history" | bash -i 2>/dev/null | sed -e 's/\x1b\[.//g'
Explanation:
The history command only works on interactive shell.
The first part:
echo "history" | bash -i 2>/dev/null
Forces interactive shell (and removes lines which aren't output of history).
The second part:
sed -e 's/\x1b\[.//g'
Removes escape character the shell might output (happened on my system).
You may pre-write the history of current session:
history -w
Then in editor you can get last, say, 20 commands of history:
:r ! tail -20 ~/.bash_history
Try:
r !set -o history; HISTFILE=~/.bash_history; history -r; history 10
This will include the timestamps and will not include history that hasn't been saved to the history file.