macosfontscolorstextedit

How to change font color of numbers in TextEdit


I was wondering if changing the color of the font for certain numbers in TextEdit was possible.

For exemple to have all '1's in blue, '2's red etc...

If that's impossible in TextEdit, can someone suggest a similar software able to do so and read .txt files ?


Solution

  • This was fun! macOS includes Perl and textutil which is used for changing document formats, so you can do something like what you want without needing to install anything...

    #!/bin/bash
    perl -pe 'BEGIN{ $/=\1; }
              s/0/<font color="red"    >0<font color="black">/ || 
              s/1/<font color="green"  >1<font color="black">/ ||
              s/2/<font color="blue"   >2<font color="black">/ ||
              s/3/<font color="cyan"   >3<font color="black">/ ||
              s/4/<font color="magenta">4<font color="black">/ ||
              s/5/<font color="yellow" >5<font color="black">/ ||
              s/6/<font color="pink"   >6<font color="black">/ ||
              s/7/<font color="orange" >7<font color="black">/ ||
              s/8/<font color="teal"   >8<font color="black">/ ||
              s/9/<font color="gray"   >9<font color="black">/ ||
              s/\n/<br>/;
             ' "$1"  | textutil -format html -convert rtf -stdin -stdout > output.rtf
    

    Save that as go and make it executable, just once with:

    chmod +x go
    

    Then you can convert any document like this:

    ./go input.txt
    

    and it will make output.rtf.

    So, if I start with the following in input.txt:

    1234567890 I love RTF and HTML but not 2 much and I can't spell, or count 1,000,222
    1 man had 2 dogs and 333 cats
    

    I end up with:

    enter image description here


    The Perl reads 1 character at a time, because of $/=\1;. It then replaces any digit with an HTML font tag with a different colour, then sets the colour back to black after the digit. The output is then passed to textutil which is told to treat the input as html and make the output RTF.


    I have spent all day on this and I still have no idea why one of your documents works and the other doesn't. The only thing I can say is that textutil seems not to crash when I comment out the following line that changes the colours of the 1s in your document to green! I have no idea why!

    s/1/<font color="green"  >1<font color="black">/ ||
    

    I re-wrote it in a different way even, but it is still the same. I will put the code below so that others can play with it:

    #!/usr/bin/env perl
    use strict;
    use warnings;
    
       my ($i, $x, %HofH);
    
       # Initialise table mapping input bytes to output/actions
       # So it's a hash of hashes, each hash stores the corresponding output string and whether it set colour
       foreach $i ('A'..'Z', 'a'..'z' ){
          $x = ord($i);
          $HofH{$x}{out}    = $i;
       }
       # Set up the coloured digits 0-9
       $i=48; $HofH{$i}{out} = sprintf("<font color='red'>0")    ; $HofH{$i}{colour}=1;
       #$i=49; $HofH{$i}{out} = sprintf("1")                      ; $HofH{$i}{colour}=1;    # THIS CRASHES TEXTUTIL ???
       $i=50; $HofH{$i}{out} = sprintf("<font color='blue'>2")   ; $HofH{$i}{colour}=1;
       $i=51; $HofH{$i}{out} = sprintf("<font color='cyan'>3")   ; $HofH{$i}{colour}=1;
       $i=52; $HofH{$i}{out} = sprintf("<font color='magenta'>4"); $HofH{$i}{colour}=1;
       $i=53; $HofH{$i}{out} = sprintf("<font color='yellow'>5") ; $HofH{$i}{colour}=1;
       $i=54; $HofH{$i}{out} = sprintf("<font color='pink'>6")   ; $HofH{$i}{colour}=1;
       $i=55; $HofH{$i}{out} = sprintf("<font color='orange'>7") ; $HofH{$i}{colour}=1;
       $i=56; $HofH{$i}{out} = sprintf("<font color='teal'>8")   ; $HofH{$i}{colour}=1;
       $i=57; $HofH{$i}{out} = sprintf("<font color='grey'>9")   ; $HofH{$i}{colour}=1;
    
       # Special cases - CR, LF, ampersand
       $i=9;  $HofH{$i}{out} = " ";
       $i=10; $HofH{$i}{out} = "<br>\n";
       $i=13; $HofH{$i}{out} = "<br>\n";
       $i=39; $HofH{$i}{out} = "&amp;";
       $i=47; $HofH{$i}{out} = "/";
       $i=61; $HofH{$i}{out} = "=";
       $i=63; $HofH{$i}{out} = "?";
       $i=40; $HofH{$i}{out} = "(";
       $i=41; $HofH{$i}{out} = ")";
       $i=45; $HofH{$i}{out} = "-";
       $i=58; $HofH{$i}{out} = ":";
       $i=59; $HofH{$i}{out} = ";";
       $i=46; $HofH{$i}{out} = ".";
       $i=44; $HofH{$i}{out} = ",";
       $i=32; $HofH{$i}{out} = " ";
       $i=60; $HofH{$i}{out} = "&lt;";
       $i=62; $HofH{$i}{out} = "&gt;";
    
       open(my $FILE, $ARGV[0]) or die $!;
       binmode($FILE);
    
       local $/ = \1;
       my $cnt=0;
       while ( my $byte = <$FILE> ) {
          my $x = ord($byte);
          if(defined $HofH{$x}){
             printf("%s",$HofH{$x}{out});
             printf("<font color='black'>") if defined $HofH{$x}{colour}
          } else {
             printf STDERR "ERROR: Character number %d ignored at byte offset %d\n",$x,$cnt;
          }
          $cnt++;
       }
    
       close $FILE;
    

    You run it with:

    thisScript.pl someFile.txt | textutil -format html -convert rtf -stdin -stdout > output.rtf