How can I add a character before every capital letter in a terminal emulator's output (for a Braille display)?

66 Views Asked by At

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}"
0

There are 0 best solutions below