Companionway

Meeting challenges with success

Dealing with strings that contain ansi codes for colorizing can be a challenge especially if you need the actual display length of the embedded strings.

Here is a quick-n-dirty function that can either exctract all the ansi_codes and provide them to you or just retrun the embedded string(s) or just return the length of the line without the ansi_codes.

# ####################################
  def parse_codes(msg, rtrn_type='dict', *args, **kwargs):
      # ################################
      """
      purpose: grab all ansi_codes from a string and return them - see below
      requires:
          - msg: str      # line string that may or may not contain ansi_codes, codes are separated from the message string
      options:
          - rtrn: str     # default='dict'  a dictionary will be returned = {'codes': ['code1', 'code2', 'code3'...], 'strings': 'str1', 'str2', 'str3', 'str4',...]}
                          # rtrn='list' returns the list of codes
                          # rtrn='string'|'str' returns string(s) joined as one string without codes
                          # rtrn='nclen'|'len' returns only thr length of the (joined) string without and codes
      returns:
          - default = {'codes': ['code1', 'code2',...], 'strings': 'str1', 'str2', ...]}
          - rtrn='list' = ['code1', 'code2', ...]
          - rtrn='string' = "".joined(['str1', 'str2', ...])
          - rtrn='len' = len("".joined(['str1', 'str2', ...]))
      notes:
          - this replaces the decrecated split_codes(), escape_ansi(), and nclen()
          - WIP
          - 20250826-1606
      """
      # """--== Local Import(s) ==--""" #
      # """--== Config ==--""" #
      rtrn_type = arg_val(["rtrn", "type", "rtrntype","rtrn_type"], args, kwargs, dflt=rtrn_type)
      # """--== Init ==--""" #
      pat = r"\x1b\[[0-9;]+m"
      msg = str(msg).strip()
      # msg = clr_coded(msg) 
      rtrn = None
      codes_l = ["",""]
      # """--== Process ==--""" # 
      codes_l = re.findall(pat, msg):
      if not codes_l:
          codes_l = ["",""]
      elems_l = re.split(pat, msg)  # <--- fails but why?
      if len(elems_l) > 2:
          elems_l =  elems_l[1:-1]  # I do not know why but it always seems to have '' both as the first and last elem
      # """--== Prepare rtrn ==--""" # 
      if rtrn_type in ('dict', "d", "dictionary"):  # default
          rtrn = {'codes': codes_l, 'strings': elems_l}
      if rtrn_type in ('list', 'lst', 'l'):
          rtrn = codes_l
      if rtrn_type in ('string', 'str', 'joined', 'stripped', 'nocode', 'escaped'):
          rtrn = "".join(elems_l)
      if rtrn_type in ('nclen', 'len'):
          rtrn = len("".join(elems_l))
      # """--== return ==--""" #
      # print(f"{rtrn_type=} {rtrn=}")  # for debugging
      return rtrn

This call arg_val() which returns the value for any rtrn_tye=‘xxx’. How that function works is aluded to in previous posts but I might go back and revisit this matter in the future.

The line that calls clr_codes(msg) has been commented out here. In my use that line calls another function that translates embedded color tags into ansi codes. For example, a string like this “This [blue]is blue[/] and this [red]is red[/]” gets translated into ‘This \x1b[34mis blue\x1b[0m and this \x1b[31mis red\x1b[0m’. Perhaps in a future post I will show how clr_coded works but that will be a lengthy post.

Thanks for reading…

Contact me if you have any questions.

Enjoy!

comments powered by Disqus

Credits

cos Companionway
ale vim ALE
netlify Deploy to Netlify
vim VIM the editor
gtoolz gtoolz
gtoolz python tools Google Gemini