Hacker Read top | best | new | newcomments | leaders | about | bookmarklet login
Your Bash Prompt Needs This (jonisalonen.com) similar stories update story
215.0 points by jonisalonen | karma 234 | avg karma 11.7 2012-04-27 15:33:47+00:00 | hide | past | favorite | 134 comments



view as:

or you just configure a two line prompt (with a \n).

Exactly. I got tired of the occasional command that didn't add a final newline, often my own sloppy "perl -e" output. So, my prompt starts with a newline, just in case the previous command had unfinished business.

That means a blank line after most commands' output, and I find that unsightly.

Is there any way of getting bash to only output a '\n' if the cursor isn't already at the start of a line?


Recommendation: Try it for a week or so, and you may not go back. I've found it to be helpful to have more space between commands.

Very helpful tip! Thanks for posting.

What if a program prints text without a newline at the end, then exits? It's possible and it would be confusing to not see that last line.

    cout >> "Hello world"; // with no endl.
Prepending the prompt with a new line might be a better idea than over-writing the current line.

Zsh handles this case pretty well. If there's no newline when a process exits, it prints a color-inverted % and a newline.

Yes. I have a two line bash prompt: the first line with a whole bunch of info like the exit status of the last command, the number of background jobs, the hostname, current username (very useful when you have 5 different ssh sessions to different machines), and the current working directory. In real world usage I have experienced almost no loss of utility from only having 50% of my command history on screen. In fact, given how many commands are just ls,whoami,jobs,pwd, that info gets condensed into one line.

Could you share your prompt?

Cool! Do you mind posting your PS1 so other people can try out your config?

Here's the PS1:

  PS1="\[\e[32;1m\]\[\e[37;1m\]\`if [ \$? = 0 ]; then echo \[\e[33m\] :\)\[\e[0m\]; else echo \[\e[31m\] X\(\[\e[0m\]; fi\`\[\e[32;1m\] \[\e[32;1m\](\[\e[37;1m\]\h:\u\[\e[32;1m\])-(\[\e[37;1m\]\j\[\e[32;1m\])-(\[\e[37;1m\]\w\[\e[32;1m\])\n\[\e[0m\]"
Here's how it appears:

   :) (seas456:narayana)-(0)-(~/personal)
  [this line is where your cursor blinks; notice no symbol at the start of this line]
You can't see the colors here. The smiley face turns into a bright red frowny face if the exit code of the last job is nonzero.

It looks like the your markup got mangled a little. Would you mind posting a gist?

Mine's very similar, and includes the current date and time; it also wraps onto the next line and starts with a # (mostly because I'm an idiot, and have burned myself by copying-and-pasting an entire-line-plus-newline and ran a command instead of just copying it in order to edit it.)

    [\[\033[1;32m\]\D{%Y-%m-%d %H:%M:%S}\[\033[0m\]] \[\033[1;32m\]\u\[\033[0m\]\[\033[1;32m\]@\h\[\033[0m\]:\[\033[1;36m\]\w\[\033[0m\]\n#
It's actually dynamically generated by my .bashrc so that different servers have different colors; at a glance, I can generally tell whether I'm on one of my machines, or on a work build server, or an amazon ec2 instance.

My prompt puts a newline if the cursor is not in the first column, but getting the cursor position complicates things.

https://github.com/dylanahsmith/dotfiles/blob/master/.config...


looks interesting, but it doesn't seem to be compatible with either my setup in general (bash 3.2.25 inside screen inside PuTTY) or my current prompt, which comes out of a shell function and embeds the number of files in pwd, username@hostname:pwd, and previous status, with coloring applied to various parts.

specifically your function just sort of sits there doing nothing when i try it....


zsh's approach is clever and doesn't require bidirectional communication. They always print their inverted "%" and then they print as many spaces as you have columns in the terminal (minus one). If the last process ended with a CRLF, they will now be in the last column of the same line; otherwise they will have wrapped around to a new line (assuming the terminal is in auto wrap mode, which is the default). Then they print a carriage return and the prompt as normal.

This does break if the terminal has auto wrap turned off (echo -e "\033[?7l"), but otherwise it's very clever.


That solution sounds even more hacky. Just like I expected resizing my iterm2 window causes glitches because it's text reflowing. I love that feature, but I realize this isn't a problem for all terminals.

Agreed. This is the reason I tried this tip many years ago and removed it.

Post says $PS1="\[\033[G\]$PS1"

But the first $ is wrong, it should read PS1="\[\033[G\]$PS1"


Even

    export PS1="\[\033[G\]$PS1"

I don't think exporting PS1 is a good idea. Child processes don't need it and if I launch a different shell with different PS1 semantics I get a broken prompt instead of whatever the default for that shell is.

Alternative - use zsh which doesn't suffer from this. (or from deleting lines with no line terminator - it inserts it's own "%" sign with inverted colour and a \n when that happens)

+1. I don't really understand why you wouldn't use zsh, or something more powerful than bash.

Because bash is the standard on Linux and every component you add introduces additional complexity and instability. It's fine to add stuff to your home machine, but you need to be careful with adding things to a server or a work environment. Bash is good enough for almost everything.

Find me a real world case where switching from bash to zsh was a bad idea.

It would be too much of a PITA for me to compile zsh for every OS/arch that I work with in a given day. I ssh to dozens of machines in a day ranging from modern Linux to ancient versions of Solaris and HPUX. Over 10 years ago we added bash to our standard software that will be on every system we have, which means I know that my bash configuration will be the same across every single platform.

Scripts with no '#' line at the top are run in bash by bash, and in sh by zsh (at least on my machine). I had a program which used a bunch of such scripts, which broke in zsh.

Even if the answer is "none", zsh will need to additionally defend "what is the advantage of zsh for someone who already knows how to use bash", as any form of switch is going to come with a cost. I would therefore be really interested in your reasons (I use bash, as currently do all of the people I know and work with; [edit: apparently except one]).

It seems like most of the features listed as better than bash are either a) covered by bash 4.0, b) bad ideas (shared history among sessions), or c) only controversially better (searching around, people seem to argue back/forth about which programmable completion implementation is faster/better).


zsh had me when I realized that

1) it's a drop in replacement for bash. All those scripts you have around have #!/bin/bash at the top, they will still work exactly as they always have.

2) You can selectively go back through your command history. You can arrow-up to go to previous commands just like in bash. But if you start a command (say, ssh) and then arrow-up you will then be cycling back through the last ways you entered that command. Super convenient.


But if you start a command (say, ssh) and then arrow-up you will then be cycling back through the last ways you entered that command.

Like Ctrl+R?


Not exactly, but similar. If you want to see a demo, Ryan Bates highlights this feature (among others) with his ZSH screencast: http://railscasts.com/episodes/308-oh-my-zsh

> You can arrow-up to go to previous commands just like in bash. But if you start a command (say, ssh) and then arrow-up you will then be cycling back through the last ways you entered that command.

Or, if you'd like to do this in Bash, and any program that uses readline: In ~/.inputrc

    # Bind the up arrow to history search, instead of history step
    "\e[A": history-search-backward
    # And the reverse (down)
    "\e[B": history-search-forward

I find it easier to just hit ^R when I want to search my history. And since that's a default keybinding, it works on any machine I touch.

I recently moved from tcsh to zsh, and this is one thing that seems to be a bit weird in zsh. For example, given

    git clone
    git rebase master
    git log
in my history, if I typed

    git r<UP>
I get 'git log', not 'git rebase master' as I'd expect.

Try:

  bindkey "^[[A" history-beginning-search-backward

And that's why no one wants to bother switching.

Actually, that's exactly why I switched. (more precisely, this could be said why: http://www.cs.elte.hu/zsh-manual/zsh_14.html)

If you don't want to use it, I don't see how that is any of my business. I was just trying to help out somebody who does, so there's hardly any reason to be an ass.


To be honest, I tried it years back and liked it, but forgot about it and didn't miss it. I may try it again sometime.

All I'm saying is that most people won't like something that offers no immediate major benefit and has annoying defaults that they have to find an obscure setting to fix. This is probably why so few use emacs, even though it is awesome :)


Everything has annoying defaults until you either change them or get used to them.

For number 2, this has been the default for tcsh for years now...

Me too; I actually use up arrow for history-search-backward and also bindkey -v, so ESC-k gives me a non-search history (like the default up arrow behaviour).

Excuse the nitpick, but what you meant to say is "All those scripts having #!/bin/bash at the top, they will still work exactly as they always have if you change the line to read #!/bin/zsh"... and it's not quite clear why you would want to do that if the script is already working as intended, hence this clarification.

Of course, a script that has #!/bin/bash at the top will keep working regardless of which shell you execute it on anyway, even a shell with a completely different syntax such as tcsh, because that shebang line will tell the OS to always use bash to execute the script--no matter what shell you're using to invoke the script.

It's different when you source a script (usually done using the eponymous shell built-in) since then the shebang line will be treated as a comment and ignored, and all other lines in the script will be executed in the context of the current shell.


I agree that using zsh has to be justified. My suggestions for bash users who want to get more out of their (interactive) shell are:

1. Learn bash better. Lots of low-hanging fruit there to increase your productivity with minimal effort.

2. Learn how to customize your environment in bash. Know what every line in your dotfiles does. Add to your dotfiles gradually as you learn.

3. If you learn about some cool features in zsh, see if bash has the feature already. If it doesn't, see if you can mimic it easily with your own functions or scripts.

4. If you still want more features, make the switch to zsh and repeat steps 1 and 2 with zsh.

I think the worst is when people see a novel trick and switch to zsh and slam in oh-my-zsh* without knowing any shell basics. Now you have another shell and a big pile of code and you don't understand any of it. This usually won't cause problems, but you almost certainly won't be getting the most out of your shell. You'd be better off in most cases just digging into bash a little deeper.

I use zsh now, but I only switched after learning what bash could do and what its limitations are. I'll reevaluate zsh vs. bash 4.0 at some point, but for now I see zsh installed by default more often than bash 4.0 and it seems to me that most users interested in the best interactive shell experience are still on zsh and I like to learn from them.

* - I think oh-my-zsh is a great project - I'm not knocking it. I've borrowed lots of great stuff from it. But I think you should understand every line of code you are dumping into your environment, whether you are using oh-my-zsh or not.


Well, I switched from csh to zsh and almost got arrested.

While a senior in high school (~15 years ago), I was also enrolled at the local university and taking a few 1000- and 2000-level Math and CS courses. About halfway into the spring semester, my account on the CS department's crusty old Sun box was locked, and my CS professor that semester told me to report to the system administrator's office after class.

When I arrived at the system administrator's office, the department's system administrator and the department head were waiting for me. The sysadmin immediately (and angrily) said that if this were anywhere but a university, he'd see that I was thrown in jail. When I asked what he was talking about, he turned to his computer, banged on the keyboard for a bit, and turned the massive CRT so I could read it.

On his screen was an e-mail I had sent him the semester before asking that he change my shell from /bin/csh to /usr/local/bin/zsh. (Solaris of that vintage didn't have chsh, so I couldn't do it myself.)

The sysadmin was absolutely convinced that zsh gave me "elevated system privileges", even though he was the one that changed my passwd entry and presumably was the one who compiled and installed zsh in the first place.

When I argued that /usr/local/bin/zsh didn't have the suid or sgid bits and therefore gave me no more access to the system than any other shell, the department head scolded me for arguing with the (experienced, wise) sysadmin.

The sysadmin changed my shell back to csh, and the department head made me sign a document stating that I wouldn't change my shell back to zsh or try to "further gain administrative access" to the system.

On the drive home, I idly wondered whether going to (a different!) college full-time in the fall was really such a hot idea...


Not actually zsh's fault, but that's pretty amusing (now, at least - I bet it wasn't amusing then).

With the caveat that you should always pick your battles...

You should have never signed that. Even if you struck the word "further", it'd probably be seen as an admission of guilt in court.


I tried, for a week, got very frustrated and switched back.

The little itch that drove me crazy was command-line editing: in bash (and all readline apps) when I have

   command long/path/to/some/file
I can press Alt-Backspace to delete 'file', or I can press Ctrl-W to delete 'long/path/to/some/file'.

I tried various hacks to make zsh do the same, then gave up.


    bindkey '^[^?' backward-kill-word 
might do the trick? (possibly '^[^h' depending on what your backspace key sends. Ctrl-v <backspace> should give you something you can copy)

This makes Alt-Backspace do the same thing as Ctrl-W, which is delete-everything-until-the-next-space. I'm missing the delete-last-segment-of-the-path function.

Edit: I know I can customize the word style using $WORDCHARS, or 'autoload select-word-style'; my problem is that I'm used to having the capability to use two different word styles at once.

I'm looking through the command list in zshzle(1), and I'm a bit confused about the differences between backward-delete-word and backward-kill-word. Some short experiments I did failed to notice any differences (foo/bar/baz M-x backward-delete-word deletes foo/bar/baz). There's also vi-backward-kill-word which deletes 'baz', then '/', then 'bar', then '/', then 'foo'. I want a key to delete 'baz', then 'bar/', then 'foo', and I've no idea how to get it...


Hrmm. It works as you want for me, but there may be some other config item I've set.

The other alternative is to try:

    autoload -U select-word-type
    select-word-type bash
which should override C-w to do what you want. I haven't looked at it enough to see if you can get both behaviours simultaneously though (and it requires a fairly recent zsh iirc)

So you could say bash is the Internet Explorer of shells. It's the default, it's what most people use, and it's good enough.

No, I would not say that.

Internet Explorer is the default on Windows because Microsoft makes it, not because it's the best option for a default.

Bash is the default because it's the best shell to be used as a default. Nobody is twisting the arm of any distribution, but they set it as the default anyway. There's a reason for that.


Because it was at some point when the decision was made, for a few distributions.

How often is this decision re-evaluated?

...personally I just hit Ctrl+C again to reset my prompt.


I think that reason is mostly inertia.

Also, because it's GNU. Just as IE is the Microsoft browser, bash is the GNU shell, and most Linux distributions are built around GNU userland.

But that's just Linux. The BSDs don't see bash as the best default, where it tends to only be available as an optional package.


I don't use zsh because I don't spend a lot of my time at the shell or do anything complex with it when I am using it. Most of my time is spent in a text editor, and for the little amount of time I spend doing things on the shell, bash (or really, whatever the heck the default shell is) has worked fine for the basic tasks I need it for. I suppose it's possible that I'd like zsh more than bash even for what I'm doing now, but honestly, I don't even think about bash. It's just there, and it works enough of the time that I don't even have any complaints about it.

I use and prefer zsh, but a lot of developers who use OSX don't realize that they're using a version of bash that's roughly 5 years out of date - from when GNU switched over from GPLv2 to GPLv3, which Apple can't use any code from.

Bash has come a long way since then and it's just a "brew install bash" away. There's absolutely no good reason to stick with the version that ships with OSX for your personal shell.

I'm not sure which zsh OSX ships with, but it should be much more up to date since it uses a BSD-like license.


The last time I tried upgrading to bash 4.0 using `brew install bash`, I was shocked to discover that it couldn't detect when I was logging in over ssh anymore. Such logins ended up giving me the non-login shell, which didn't source any of my normal stuff.

Which Apple _won't_ use any code from. They're certainly capable of doing so, both legally and physically. They choose not to.

A lot of companies won't use any code in GPLv3.

"Legally capable" is one thing, "completely out of any possible problems in the future" is another.


Which Apple _can't_ use any code from without releasing the source code to Mac OS X.

GPL3 is toxic.


Not really. GPL3 differs from GPL2 in following things:

1) Patents, i.e. you can't circumvent GPL3 by using GPL software as something you build your software on, but then don't share it because while source code may be available, you patent the code. It was possible with GPL2.

2) DMCA, i.e. you can't circumvent GPL3 with using DMCA which makes circumventing DRM illegal in US. It was possible with GPL2.

3) Tivoization, i.e. you can't circumvent GPL3 using digital encryption, when you release the source code, but not the necessary cryptographic keys.

In other ways, GPL3 is pretty much the same as GPL2. Using GPL3 bash would not make Apple release source code of Mac OS X any more than using GPL2 bash. The only reason not to use GPL3 (1) is when you don't want the three things I listed above taken from you. I would suggest that makes any company with "no GPL3" policy toxic, not GPL3.

Should you want to educate yourself, here's a link that explains it pretty well: http://www.linuxfordevices.com/files/misc/GPLv2_vs_GPLv3.pdf

(1): It's very different with AGPL


> something more powerful than bash

Power beyond need or capability is complexity (the bad kind).


I spend a lot of time in the shell and it's so incredibly rare for what I'm doing to be limited by bash that it's hard to describe switching to zsh as anything other than a premature optimization.

Part of this is because I try to automate anything I do more than once or twice and I use a real language to do so. For anything non-trivial the differences between zsh and bash are an order of magnitude less significant than either compared with Python, Ruby, etc.


c.f.the banal argument often put forward by OSS zealots, "why use Windows, Linux is so much better".

In brief, bash, like mysql (or Windows) is always there. Most people know how to use bash and wouldn't notice any difference by switching (except for a possible unnecessary learning curve).

Lets turn it around. Assuming (and a big assumption) that zsh is more powerful, why does this matter to someone who probably spends most of their time at a terminal thinking and puts anything half way repetitive into a script? Its like telling a carpenter than a brand X chisel is more powerful than a brand Y chisel.

Show me how a skilled zsh user is 'more powerful' than a skilled bash user at anything that matters. Perhap some people spend too much time typing and not enough time thinking.


Maybe you happen to be one of those developers who's happy and comfortable to make the app/project using whatever externally mandated set of tools happen to be at hand. That's an advantage, even though it I think it also has a flip side.

I don't personally believe that bash suffers from this (I certainly can't replicate it, as further described in my other comment), and would love to see a more step-by-step reproduction of the problem.

I just do most of my bash work in emacs shell mode.

me too for a couple months now - there are a lot of rough edges - any tips? i have serious prompt issues, i have intermittently malformed colors. is your configuration on github?

turns out i'm willing to tolerate a lot of pain to have emacs operations in a shell buffer, haha


What kind of prompt issues do you have? I've set my Emacs up so that each shell has a prompt in the form name:directory> where name is the buffer name and directory is the current directory, and both name and directory are in different colors, and it all works well.

As far as colors go, shell mode does its own highlighting. I used to have problems with ANSI code colors, but they have been working properly recently. (I just tried ls --color=always which worked as expected, unexpectedly.)

Which version of Emacs are you on?

Note that this is all without any configuration. The only thing I did was add a command for opening a new shell in the current directory which turned out to be extremely useful. It even works for remote files, so now I use shell mode for almost everything.


Seems like ^L usually clears things up when this happens.

That's what I came to post. Yes, the terminal gets mixed up because it handled input that bash didn't see. And that's annoying (really it's a bug, just one so ancient no one is interested in fixing it anymore).

But terminal corruption used to be far more common (line noise, etc...) and bash has a built-in escape for this. Ctrl-L (chosen for the analogy with form-feed/"vertical tab" on a printer) will blank the screen and redraw your current edit environment at the top.


I don't see it as a bug; the shell shouldn't get to see what was written to the terminal?

BTW, it's the readline library that handles the Ctrl-L key binding to clear the screen rather than bash per se.

    $ bind -p | grep '\\C-l'
    "\C-l": clear-screen
    $

System commands are CTRL-ALT-letter CTRL-ALT-C

User plugins are mostly ALT-letter/ALT-SHIFT-letter

Editor commands are often CTRL-letter


greate

wouldn't typing 'reset' fix this?

Or just hitting enter to get a new line - this is trying to make a more permanent solution to this common issue.

zob ~ ? bob^C

zob ~ ? cat

^C zob ~ ?

default bash settings real termina, like xterm this is bash of course.

and its better than ^C is not erased.


Can you say more about the testing configuration you are using? With OS X 10.6.8, xterm 251, bash 3.2.48(1), and with no .bashrc, and after trying to set my PS1 to match yours (failing, as the lightning bolt came up as an o with an umlaut), I get the following behavior for the same test:

    saurik ~ ö bob
    saurik ~ ö cat
    ^C
    saurik ~ ö

your term looks ok im using linux and konsole bash 4.2.24(2)-release

the lightning bolt is just an utf8 fancy char

this is my PS1 if you like it: \[\e[0;32m\]\u\[\e[m\] \[\e[1;34m\]\w\[\e[m\] \[\e[1;33m\]?\[\e[m\] \[\e[1;37m\]


One could comment the "very long command" with # and it would appear in the history... no hacks.

this is hotkeyed to Meta-# by default

(one of the readline features i rediscover every three months or so and promptly forget)


Tested and it works brilliantly... it's definitely faster than C-a # RET... Thanks for the tip.

it's fully customizable too. e.g. if you work in a LISP REPL and use rlwrap to provide readline functionality, you could put this in your ~/.inputrc:

    $if lisp
            set comment-begin ;
            M-;: insert-comment
    $endif

Recently, I have really wished for a "better terminal". Particularly as my number of processors go up, I want to be able to start a program in the background and not have it's output all over the screen. I've tried various solutions (redirect to temp file -- have to remember where it is, keep starting new tmux sessions, end up with too many windows most of which I don't want). I feel there should be something better. Personally, I take a GUI solution, where programs look more like a tree, and I can easily explore / close / duplicate branches.

Have you tried gnu screen? It isn't a gui interface, so you have to learn a few hotkeys, but it's one of the better options.

He mentioned tmux, which is very similar to Screen, so I suspect that wouldn't address his issues.

http://tmux.sourceforge.net/


tmux is similar to screen. I can keep opening hotkeys to open new windows to run commands in, but then I have to remember to go back to those windows to look at the results of those commands, etc.

It doesn't really help me "maximise my processor usage" I find.


I believe iTerm2 on OS X hooks into tmux somehow to alert you when something has happened in one of your windows. I assume there's a way to make that happen on other platforms too.

Unfortunately last time I checked it was only for a branch of tmux. They are trying to get it into mainline but I don't think that has happened yet.

So what you are saying is you want a more powerful version of regular shell background capabilities? You don't want output to interrupt your interactive session, but you don't want to have to remember to visit the output later.

Do I have this right?


I think so. I might not know what I want until I have it, or don't have it :)

I just went through the following steps recently:

1) Put more things in the background with '&' - but if they have a lot of output they make your terminal usuable.

2) I could ' >t 2&>1 & ' , but then I have to remember to check t when the process finishes, and end up with lots of tiny files everywhere.

3) I could just send output to /dev/null , but then maybe I care what it was if the process fails.


Perhaps you could alias a function that pipes like tee, and checks for errors. Like this:

  alias myfunc "errorchecker >& /dev/null"
  [command] | myfunc
What it does with those errors is up to you, though your main options are "print them" (in which case, just don't redirect stderr), "log them for fetching" (and write a little command to access & manage the failure reports), or "email them to yourself".

I guess basically what I'm getting at is, look at distributed processing backends such as LSF or GRD for inspiration.


Sounds like #2 could work if you had some sort of desktop notification system. Then you could write a small script that runs your command line with stdout and stderr redirected to temp file(s), and then alerts you when the process is done, and what the temp filenames are. You could check on your running jobs with 'ps -C scriptname'

Or maybe opens them in $EDITOR...like this (I can't get it to work when $* has a pipe in it, unfortunately)

    #!/bin/bash
    out1=`tempfile -d $HOME/logs`
    out2=`tempfile -d $HOME/logs`
    $* >$out1 2>$out2
    $EDITOR $out1 $out2 # Replace this with call to notification app and/or logic based on $?/size of $out2

Tmux and screen have modes that allow you to 'watch' a window for activity, and alert you to this. They can even watch for inactivity, and warn you when something finishes. You can also use "echo ^v^g" (where ^ is ctrl) to summon a bell, tmux and screen can be configured to alert you to such a bell.

I generally use nohup so I don't have to worry about killing the program when I log out. The man page has a handy bash script for "launch" that captures stdout and stderr to separate files.

http://ss64.com/bash/nohup.html


Not a general solution for your problem, but you could use GNU parallel anytime you'd use xargs (they use the same API).

Why not just open a new terminal?

Have you tried tmux's window monitoring settings? tmux can beep you when a window becomes active, goes silent, or prints a particular string—which will presumably make your terminal emulator yell at you somehow, too.

I used to do this in my prompt, but it caused more problems than it solved, since sometimes programs actually put legitimate output on the last line without a terminator.

The simpler fix is just to notice that your prompt has shifted over (it's almost impossible not to notice) and just hit return before doing anything.


I added a newline (\n) to the beginning of my prompt. This way I never lose program output -- and also it's easier to see where previous commands begin and end in the scrollback buffer.

You also get tons of blank lines, right? That would annoy the heck out of me.

My prompt is five lines tall, including three blank lines. I did that, along with some bright green coloring, to make the prompt easier to spot as I rapidly scroll up through a mountain of output from my last command.

zsh prompt:

PROMPT='

%{$prompt_default_color%} %~ %* %{${fg[$prompt_user]}%}%n%{$prompt_default_color%}@%{${fg[$prompt_host]}%}%M%{$prompt_default_color%} ${vcs_info_msg_0_}_

$ %{${fg[default]}%}'


All too often, this "erases" legitimate output. I just prefix my prompt with a \n, personally.

Nitpick - shouldn't it be

    PS1="\[\033[G\]$PS1"
instead of

    $PS1="\[\033[G\]$PS1"

Yes, you are correct. I think it's better than nitpicking when it makes the code run correctly.

I honestly cannot replicate either of these behaviors, even using the OS X Terminal application (which definitely causes serious cursor synchronization issues with complex prompts due to incorrect terminal emulation: use iTerm2 instead), and even using an old version of bash (tested on both Linux and OS X).

A) When I hit ^C, I am always seeing a newline occur after the ^C and before my prompt is redrawn. I have tried this with cat (blocked on read) and ssh (blocked on password).

B) When I purposely attempt to cause this (using echo -n and interpreting "a very long command" to mean "long enough that it wrapped to the next line"), hitting up redraws and overwrites part of the prompt in order to guarantee that the position of the prompt will edit correctly.


I have had this problem before, usually when using a repl that gets abnormally terminated. I don't know exactly what causes it and I haven't been able to replicate it deliberately. Long commands alone don't seem to trigger it.

I found the problem occurred most frequently when testing APIs with cURL. Repeat the last command (with output) a few times, and then the cursor loses position when you decide to edit it.

Even better, if you want to edit a long command, use C-x C-e (remember to have EDITOR set to your editor of choice).

I never knew this, this is absolutely going to be a timesaver!

Hmm, I don't have this issue. Perhaps because I use a two-line prompt?

    export PS1="\n\W\$(parse_git_branch) $ "

    parse_git_branch() { git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/(\1)/'; }

You use a custom git parse branch, while git has a much more powerful prompt function : __git_ps1 . It's readily available in git's default bash_completion.d file. It shows the current branch, but also the state of the git tree (during rebase, am, bisecting, cherry-picking, etc.)

http://tldp.org/LDP/LGNET/122/lg_tips.html

I set mine to standard for successful output "[user@host:truncated path]$ ".

Having my shell smile at me all the time makes me think it's up to something.


alternate solution using readline: set echo-control-characters Off

zsh is relatively large compared to bash. and bash is large compared to sh, rc, tcsh, etc. if there are space and memory constraints, size is relevant.

the path to "user-friendly" shell nirvana (i.e. interactive use, not scripts) can be achieved through use of a library like editline, without installing a huge, "kitchen sink" package like zsh... if size is an issue. make the shell cmd line behave like the editor you know well.


anyway, who's using bash nowadays? there's zsh...

Put a blank line at the beginning of your PS1 instead. This has the added benefit of clearly separating every command. My PS1 actually is this:

  rpatterson@rpatterson-tba 04/27/2012 01:24 PM ~
  $ 
This gives me a full row to type a command, and lets me see how long ago the last command finished. Each of those components is bold and colored differently.

I do this too. It helps me to have a blank line between invocations of different commands.

    [prakash@kaveri 16:39:05 ~ :) ]
    >> sleep 10
    ^C

    [prakash@kaveri 16:39:18 ~ :( ]

I assume the smilies drive off of $? ? Interesting idea....

So...your interrupted 'sleep 10' took 13 seconds?

No, the time between when the first PS1 was printed and when he pressed ^C was approximately 13 seconds.

Of course, my bad.

This has a side-effect that I don't like. Python's virtualenv, once activated, places the string '(venv)' (assuming you named it 'venv') immediately before your prompt to let you know that it is active in this terminal. However, this export hides this modification, and it makes it difficult for me tell whether the venv is active or not.

Personally I do not use virtualenv activation. Instead I prefer to explicitly launch Python and/or scripts with bin/python, bin/scriptname etc., either with my current working directory in the virtualenv, or by creating a symlink ./bin -> .virtualenv/bin in the project root.

When you use this in your prompt this will not show any result

$ echo -n foo bar


Couldn't you just hit enter after hitting control-C to bring up a new prompt below the one with the ^C in it?

I don't have this problem (even though I don't use bash) since the first character in my prompt is a newline. I think it makes things easier to read in general.

Sorry, I think it's a problem not worth solving; it's helpful to know this has occurred by the state the screen is in. If you want to solve it correctly then, since it's also common to have the cursor left bereft in the middle of a screen of text,

    PS1='\['"$(tput cr)$(tput ed)"'\]$ '
is better since it clears to the end of the screen, e.g. try

    seq 1000 | fmt; tput cup 10 20
with and without it.

But the thing is, with either that approach or the one in the article, you're wiping out what may be useful; that unfinished line causing PS1 to be pushed along may have vital data on it, data that's hard to re-create.


When I see this, I tend to automatically hit Ctrl+L to clear the screen and re-position the prompt. Quick and easy. I scroll up if I need to study the output further.

I've always found putting $? handy. This is the exit status of the last command, and when non-zero means the program wasn't successful or encountered an error.

Why isn't the last line in shells dedicated only to the prompt? The commands' output could scroll in the remaining lines.

In my past experience, prompt/history corruption is quite often due to missing/incorrect use of \[ and \] around all the non-printing sequences (colours, formatting, etc), which cause Bash to compute the length of the prompt incorrectly, and cause redrawing woes.

Worth double-checking, anyway. I've occasionally pondered some sort of prompt-lint/validator given the reams of dubious examples out there, and problems people face when customising their own.


Legal | privacy