M4444 / TMatrix

Terminal based replica of the digital rain from The Matrix.
GNU General Public License v2.0
380 stars 14 forks source link

Custom Character sets #25

Open frnco opened 4 years ago

frnco commented 4 years ago

I am surprised by how great TMatrix's output is, the gradient looks amazing, and I think another good feature would be giving more control on which characters are shown.

The idea comes from will8211/unimatrix and the implementation there is actually very simple, there are two command-line parameters, one for predetermined charsets and other for custom characters. I believe even just one of the two strategies would already be a good additioon to TMatrix, and sooner or later I'll probably implement this to some extent even if just for me to use it, so I may be able to send a PR.

The implementation on Unimatrix is pretty simple:

First there's an Object/Hash/etc with the predefined charsets:

char_set = {
    'a': 'qwertyuiopasdfghjklzxcvbnm',
    'A': 'QWERTYUIOPASDFGHJKLZXCVBNM',
    'c': 'абвгдежзиклмнопрстуфхцчшщъыьэюя',
    'C': 'АБВГДЕЖЗИКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ',
    'e': '☺☻✌♡♥❤⚘❀❃❁✼☀✌♫♪☃❄❅❆☕☂★',
    'g': 'αβγδεζηθικλμνξοπρστυφχψως',
    'G': 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ',
    'k': 'ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン',
    'm': 'ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン1234567890'
         '1234567890-=*_+|:<>"-=*_+|:<>"-=*_+|:<>"-=*_+|:<>"',
    'n': '1234567890',
    'o': 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890'
         '`-=~!@#$%^&*()_+[]{}|\;\':",./<>?"',
    'p': '',
    'P': '',
    'r': 'mcclllxxxxvvvvviiiiii',
    'R': 'MCCLLLXXXXVVVVVIIIIII',
    's': '-=*_+|:<>"',
    'S': '`-=~!@#$%^&*()_+[]{}|\;\':",./<>?"',
    'u': args.custom_characters}

Then for the charsets option just concatenate the characters for each specified Charset into a Variable with all possible characters. And to make things even simpler, the custom characters passed through the parameter are saved as one of the charsets:

# "-l" option has been used
if args.character_list:
    chars = ''
    for letter in args.character_list:
        try:
            chars += char_set[letter]
        except KeyError:
            print("Letter '%s' does not represent a valid character list."
                  % letter)
            exit()

And just pick a random character from the all-possible-characters variable to display:

@staticmethod
def get_char():
    """
    Returns a random character from the active character set
    """
    return chars[randint(0, chars_len)]

This has the advantage of specifying not only which characters are available but also how common or rare each character is.

I'd probably use a lambda for the "m" charset and maybe using a lambda or something to generate charsets in a cleaner way

In Ruby (which is my go-to language) for instance, I can do stuff like this:

irb(main):019:0> puts ("A".."z").to_a.join.concat (0..9).to_a.join
ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz0123456789

So putting that together with my love for hackish stuff, I'd most likely consider taking arguments formatted as something like:

--custom="0..9,A..Z, ,a..z,12345"

...so I could do this kinda madness:

irb(main):009:1* "0..9,A..Z, ,a..z,12345".split(",").map{|i| 
irb(main):010:1*   next i.to_s unless i.match? /^.\.\..$/
irb(main):011:1*   i.split("..").inject{|f,l|(f..l).to_a.join}
irb(main):012:0> }.join
=> "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz12345"

Or the slightly more readable and less quirky:

irb(main):014:0> input = "0..9,A..Z, ,a..z,12345"
irb(main):015:1* input.split(",").map{|item|
irb(main):016:2*   if item.match? /^.\.\..$/
irb(main):017:2*     item.split("..").inject{|first,last|(first..last).to_a.join}
irb(main):018:2*   else
irb(main):019:2*     item.to_s 
irb(main):020:1*   end
irb(main):021:0> }.join
=> "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz12345"

Pretty neat for less than 10 lines of code, if I do say so myself... And I think this covers pretty much everything I might want.

M4444 commented 4 years ago

Thanks! Adding custom characters might be useful for some people. I'll take a look at it.