Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I make my terminal prompt extend the width of the terminal?

I noticed in this video, that the terminal prompt extends the entire width of the terminal before breaking down to a new line. How can I set my PS1 variable to fill the remaining terminal space with some character, like the way this user did?

The issue is, I don't know how to update the PS1 variable per command. It seems to me, that the string value for PS1 is only read in once just as the .bashrc file is only read in once. Do I have to write some kind of hook after each command or something?

I should also point out, that the PS1 variable will be evaluated to a different length based on the escape characters that make up it. For example, \w print the path.

I know I can get the terminal width using $(COLUMNS), and the width of the current PS1 variable with ${#PS1}, do the math, and print the right amount of buffer characters, but how do I get it to update everytime. Is there a preferred way?

like image 866
Trevor Hickey Avatar asked Jan 26 '14 01:01

Trevor Hickey


People also ask

How do you increase terminal width?

Quick tip: You can also use the Ctrl + Shift , (comma) keyboard shortcut to open the settings page. Click on Startup. Under the “Launch size” section, use the Columns option to adjust the width of the Windows Terminal. Under the “Launch size” section, use the Rows option to adjust the height of the Windows Terminal.

How do I set terminal width in Linux?

You should go to Edit->Profile Preferences, General page and check Use custom default terminal size, and then set your preferred horizontal and vertical dimensions.


2 Answers

Let's suppose you want your prompt to look something like this:

left text----------------------------------------------------------right text
prompt$ 

This is pretty straight-forward provided that right text has a known size. (For example, it might be the current date and time.) What we do is to print the right number of dashes (or, for utf-8 terminals, the prettier \u2500), followed by right text, then a carriage return (\r, not a newline) and the left text, which will overwrite the dashes. The only tricky bit is "the right number of dashes", but we can use $(tput cols) to see how wide the terminal is, and fortunately bash will command-expand PS1. So, for example:

PS1='\[$(printf "%*s" $(($(tput cols)-20)) "" | sed "s/ /-/g") \d \t\r\u@\h:\w \]\n\$ '

Here, $(($(tput cols)-20)) is the width of the terminal minus 20, which is based on \d \t being exactly 20 characters wide (including the initial space).

PS1 does not understand utf-8 escapes (\uxxxx), and inserting the appropriate substitution into the sed command involves an annoying embedded quote issue, although it's possible. However, printf does understand utf-8 escapes, so it is easier to produce the sequence of dashes in a different way:

PS1='\[$(printf "\\u2500%.0s" $(seq 21 $(tput cols))) \d \t\r\u@\h:\w \]\n\$ '

Yet another way to do this involves turning off the terminal's autowrap, which is possible if you are using xterm or a terminal emulator which implements the same control codes (or the linux console itself). To disable autowrap, output the sequence ESC[?7l. To turn it back on, use ESC[?7h. With autowrap disabled, once output reaches the end of a line, the last character will just get overwritten with the next character instead of starting a new line. With this technique, it's not really necessary to compute the exact length of the dash sequence; we just need a string of dashes which is longer than any console will be wide, say the following:

DASHES="$(printf '\u2500%0.s' {1..1000})"
PS1='\[\e[?7l\u@\h:\w $DASHES \e[19D \d \t\e[?7h\]\n\$ '

Here, \e[19D is the terminal-emulator code for "move cursor backwards 19 characters". I could have used $(tput cub 19) instead. (There might be a tput parameter for turning autowrap on and off, but I don't know what it would be.)

The example in the video also involves inserting a right-aligned string in the actual command line. I don't know any clean way of doing this with bash; the console in the video is almost certainly using zsh with the RPROMPT feature. Of course, you can output right-aligned prompts in bash, using the same technique as above, but readline won't know anything about them, so as soon as you do something to edit the line, the right prompt will vanish.

like image 137
rici Avatar answered Nov 30 '22 04:11

rici


Use PROMPT_COMMAND to reset the value of PS1 before each command.

PROMPT_COMMAND=set_prompt
set_prompt () {
    PS1=...
}

Although some system script (or you yourself) may already use PROMPT_COMMAND for something, in which case you can simply add to it.

PROMPT_COMMAND="$PROMPT_COMMAND; set_prompt"
like image 29
chepner Avatar answered Nov 30 '22 04:11

chepner