23

I have a bash script which generates a motd. The problem is depending on some terminal settings which I am not sure about the color will extend to the end of the line. Othertimes it doesn't:

e.g.

square

v.s.

jagged

IIRC one is just the normal gnome-terminal and the other is my tmux term. So my question is how can I get this to extend to 80 character (or really to the terminal width). Of course I can pad to 80 chars but that really doesn't solve the problem.

Here is a snip of my code which generates the motd:

TC_RESET="^[[0m"                                                                
TC_SKY="^[[0;37;44m"                                                            
TC_GRD="^[[0;30;42m"                                                            
TC_TEXT="^[[38;5;203m"   

echo -n "${TC_SKY}                                                                              

... lots of printing..." 
echo -e "\n                           Welcome to Mokon's Linux!                           \n"

echo -n "${TC_GRD}"                                                             
nodeinfo # Just prints the info seen below...                                                                       
echo ${TC_RESET} 

How can I programmatically from bash change the terminal settings or something change the color to the end of the line?

David Mokon Bond
  • 1,576
  • 2
  • 18
  • 42

3 Answers3

21

Maybe use the Escape sequence to clear-to-EOL

For some reason (on my MacOS terminal!) I only needed specify this sequence and then it worked for all the lines but for completeness I list it for all

TC_RESET=$'\x1B[0m'
TC_SKY=$'\x1B[0;37;44m'
TC_GRD=$'\x1B[0;30;42m'
TC_TEXT=$'\x1B[38;5;203m'
CLREOL=$'\x1B[K'

echo -n "${TC_SKY}${CLREOL}"
echo -e "\n           ABC${CLREOL}\n"
echo -e "\n              DEFG${CLREOL}\n"

echo -n "${TC_GRD}"
echo -e "\n           ABC${CLREOL}\n"
echo -e "\n              DEFG${CLREOL}\n"
echo ${TC_RESET}
nhed
  • 5,774
  • 3
  • 30
  • 44
  • 3
    Thank You! And Thanks to the others who also tried but this solutions works the way I was hoping. I made a few alterations. Basically I append to a temp file and then use send to replace all the newlines with a newline and that char. If I don't put that escape sequence on each line I only get it on the lines with it... I'll add that to your answer for others... – David Mokon Bond Nov 18 '13 at 23:35
  • @DavidMokonBond My sample was based on experimentation on my Mac, obviously you are using a wider set of terminals. So I updated my answer - can you validate? – nhed Nov 19 '13 at 16:45
  • I don't use `tmux`, what is the reported terminal type (`${TERM}`) and is the behaviour similar on `screen`? – nhed Jan 18 '15 at 02:50
  • Yes, its very similar to screen. For now I just sent it through sed and padded it to 80 chars which works enough for me. Here is the term: i:echo ${TERM} screen-256color After googling a bit I think it might be due to tmux not supporting all the same term features such as the eol line one you are using but I'm not really sure – David Mokon Bond Jan 18 '15 at 02:59
  • I know it functions like screen, I was asking if your app behaves in screen as it does in tmux. Padding will of course work, but can get tricky as you may have some invisible characters. if i had to pad I would consider using printf in bash (`printf ">>%-80s<<\n" "hello"`) – nhed Jan 18 '15 at 06:22
  • 1
    The clear-to-EOL works perfectly on OS X/macOS (tested most recently on OS X 10.11.6) in the standard Terminal. Thanks for this great tip! – bluebinary Dec 27 '16 at 00:14
  • looks like recent tmux (~2.4) [fixes this](https://github.com/tmux/tmux/commit/4179b4242411f41a22d9743b4eff3b19ef69b3e8) – Dave Goodell Apr 25 '17 at 00:22
  • I'm not sure what the deal is, but the color staying to the end of the line doesn't take effect until after the first newline. So it seems that an extra line has to get used up. Wonder if this can be avoided. For example `echo "^[K^[[44;33m11111\naaaaa\nbbbbb^[[m"` the `11111` doesn't get the proper treatment – Steven Lu Jul 02 '18 at 16:21
3

Padding filter

Unfortunely, you have to pad each line with exact number of spaces for changing the color of the whole line's background.

As you're speaking about , my solution will use bashisms (Won't work under other shell, or older version of bash).

  • syntax printf -v VAR FORM ARGS assign to varianble VAR then result of sprintf FORM ARGS. That's bashism, under other kind of shell, you have to replace this line by TC_SPC=$(printf "%${COLUMNS}s" '')

You may try this:

... lots of printing..." 
echo -e "\n                           Welcome to Mokon's Linux!                           \n"

echo -n "${TC_GRD}"

printf -v TC_SPC "%${COLUMNS}s" ''

nodeinfo |
    sed "s/$/$TC_SPC/;s/^\\(.\\{${COLUMNS}\\}\\) */\\1/" # Just prints the info seen below...

echo ${TC_RESET}

enter image description here Maybe you have to ensure that $COLUMNS is correctly setted:

COLUMNS=$(tput cols)

As you could see, only the result of command filtered by sed is fully colored.

you may

  • use same filter many times:

    cmd1 | sed '...'
    cmd2 | sed '...'
    
  • or group your commands to use only one filter:

    ( cmd1 ; cmd 2 ) | sed '...'
    

But there is an issue in case you try to filter ouptut that contain formatting escapes:

(
    echo $'\e[33;44;1mYellow text on blue background';
    seq 1 6;
    echo $'\e[0m'
) | sed "
  s/$/$TC_SPC/;
  s/^\\(.\\{${COLUMNS}\\}\\) */\\1/"

unterminated sample

Il the lines you have to pad to contain escapes, you have to isolate thems:

(
    echo $'\e[33;44;1mYellow text on blue background';
    seq 1 6;
    echo $'\e[0m'
) | sed "
  s/\$/$TC_SPC/;
  s/^\\(\\(\\o33\\[[0-9;]*[a-zA-Z]\\)*\\)\\([^\o033]\\{${COLUMNS}\\}\\) */\\1\\3/
"

enter image description here

And finally to be able to fill terminate very long lines:

(
    echo $'\e[33;44;1mYellow text on blue background';
    seq 1 6;
    echo "This is a very very long long looooooooooong line that contain\
       more characters than the line could hold...";
    echo $'\e[0m';
) | sed "            
  s/\$/$TC_SPC/;
  s/^\\(\\(\\o33\\[[0-9;]*[a-zA-Z]\\)*\\)\\(\\([^\o033]\\{${COLUMNS}\\}\\)*\\) */\\1\\3/"

Nota: This only work if formating escapes are located at begin of line.

F. Hauri - Give Up GitHub
  • 64,122
  • 17
  • 116
  • 137
1

Try with this:

echo -e '\E[33;44m'"yellow text on blue background"; tput sgr0
andrea.marangoni
  • 1,499
  • 8
  • 22