0

I've been playing around with bash a bit and was wondering if it is possible to make blinking text stop if I execute another command. E.g. echo -e '\033[5mEXAMPLE\033[0m' will output a blinking EXAMPLE text; however, I'd like to know if it's possible to make the text to stop blinking if a second command is executed.

telometto
  • 1,975
  • the blinking is not handled by bash but by your terminal. So search if the terminal has such option instead. – A.B Jan 16 '23 at 20:12
  • see also https://unix.stackexchange.com/questions/3759/how-to-stop-cursor-from-blinking – A.B Jan 16 '23 at 20:16
  • @A.B Thank you, but it is not the cursor that blinks. If you check the command I mentioned in my post, you can see that I am talking about actual blinking text (intended functionality). – telometto Jan 17 '23 at 19:11

2 Answers2

5

Sending the <ESC>[5m sequence tells the terminal to set the blinking attributes of characters it will display from now on.

On most terminals, <ESC>[25m turns that off in that characters that will be sent thereafter will have their blink attribute off. <ESC>[0m, same as <ESC>[m turns all character rendition attributes off including bold, standout, colour, etc. Not just blinking.

Sending those sequences won't change what has already been displayed.

For that EXAMPLE somewhere on the screen to stop blinking, you'd have to send a new EXAMPLE at the same position with blinking off that overwrites it.

For example:

printf '\r\33[5m%s\33[25m' EXAMPLE; sleep 5; printf '\r%s\n' EXAMPLE

Would display a blinking EXAMPLE, then 5 seconds later, move the cursor back to the start of the line (CR aka \r moves the cursor to the start) and overwrite it with a non-blinking EXAMPLE.


With some terminals¹, it is also possible to change the attributes of all the characters in a region of the display using the <ESC><top>;<left>;<bottom>;<right>25$r DECCARA escape sequence, defaulting to the entire screen if the boundaries are not specified. The DECSACE escape sequence can be sent to decide whether those two <top>;<left> and <bottom>;<right> coordinates are the first and last characters or the corners of a rectangular area.

Example:

printf '\33[;;;;$r'

Would remove all the blinking on the entire screen.

To remove the blinking for some particular contiguous text on screen with that, you'd need to know the coordinates of the first and last character of that text.

You can query the cursor position with the <ESC>[6n escape sequence.

With bash, you can do that and read its <ESC>[<y>;<x>R response with:

getpos() { IFS=$'\e[;' read -rsdR -p $'\e[6n' _ _ "$2" "$1"; }

assuming the user is not typing anything at the same time or before, where:

  • the escape sequence is sent as the prompt
  • we tell read to disabled echo with -s so the response doesn't show on the screen
  • the response is read raw up to the R delimiter.
  • Field Splitted on any of the <ESC>, [, ; characters, storing the resulting fields in the _, _, $2 and $1 variables.

So you can do:

printf '\33[5m%s\33[25m\n' 'Some earlier blinking text'
getpos x1 y1; printf '\33[5m%s\33[25m%s' EXAMPLE; getpos x2 y2
printf ' \33[5m%s\33[25m\n' 'Some extra blinking text'
echo 'Some more text'

And later, assuming there's been no scrolling:

printf '\33[%s;%s;%s;%s;25$r' "$y1" "$x1" "$y2" "$x2"

In all the above, we use printf instead of echo to make it portable across different shells, or different builds / versions / settings thereof. With the printf builtin of bash and most other printf implementations, you can use \e instead of \33.


¹ that is far less widely supported than the other escape sequences mentioned here. Also note that neither tmux nor screen support it, even if the host terminal does. While it may be possible to convince them to pass the sequence along to the host, that would still not work properly with split windows.

1

Blinking text

tput blink

Revert characteristics

tput sgr0

For example

tput blink; echo This is blinking text; tput sgr0

Or

blink=$(tput blink) noblink=$(tput sgr0)
printf '%s\n' "Here we go: ${blink}this blinks${noblink} and this is steady"

Armed with this and the ability to move the cursor up (tput cuu1) or even to an absolute position (tput cup Y X - (0,0) is top left) you can overwrite the blinking text with non-blinking text as you will.

It's worth reading more about terminfo; you can even save the current cursor position, move to a new spot to write your text, and then revert the position. And if your terminal doesn't support this then provided $TERM matches reality you'll simply fall back to an approximation

Chris Davies
  • 116,213
  • 16
  • 160
  • 287
  • Note that terminfo has no steady capability to reverse blink (which is \e[25m on most terminals), only sgr0 (\e[m on most terminals) to turn all of them off, so you're left with determining the escape sequence by yourself. – Stéphane Chazelas Jan 17 '23 at 06:04
  • @StéphaneChazelas yes, that's right. I've never understood why terminfo offers other attribute pairings but only attribute reset to complement bold – Chris Davies Jan 17 '23 at 08:00