docstr: Produce the next token and bit of text.
  
  Interprets the ANSI code (which may be a color code or some other
  code), changing the lexer state and producing a new token. If it's not
  a color code, we just strip it out and move on.
  
  Some useful reference for ANSI codes:
    * http://ascii-table.com/ansi-escape-sequences.php
docstr_tok: ["Produce","the","next","token","and","bit","of","text",".","Interprets","the","ANSI","code","(","which","may","be","a","color","code","or","some","other","code",")",",","changing","the","lexer","state","and","producing","a","new","token",".","If","it","'s","not","a","color","code",",","we","just","strip","it","out","and","move","on",".","Some","useful","reference","for","ANSI","codes",":","*","http",":","\/\/ascii-table.com\/ansi-escape-sequences.php"]
code: def process(self, match):
      """Produce the next token and bit of text.
  
      Interprets the ANSI code (which may be a color code or some other
      code), changing the lexer state and producing a new token. If it's not
      a color code, we just strip it out and move on.
  
      Some useful reference for ANSI codes:
        * http://ascii-table.com/ansi-escape-sequences.php
      """
      # "after_escape" contains everything after the start of the escape
      # sequence, up to the next escape sequence. We still need to separate
      # the content from the end of the escape sequence.
      after_escape = match.group(1)
  
      # TODO: this doesn't handle the case where the values are non-numeric.
      # This is rare but can happen for keyboard remapping, e.g.
      # '\x1b[0;59;"A"p'
      parsed = re.match(
          r"([0-9;=]*?)?([a-zA-Z])(.*)$",
          after_escape,
          re.DOTALL | re.MULTILINE,
      )
      if parsed is None:
          # This shouldn't ever happen if we're given valid text + ANSI, but
          # people can provide us with utter junk, and we should tolerate it.
          text = after_escape
      else:
          value, code, text = parsed.groups()
  
          if code == "m":  # "m" is "Set Graphics Mode"
              # Special case \x1b[m is a reset code
              if value == "":
                  self.reset_state()
              else:
                  values = value.split(";")
                  for value in values:
                      try:
                          value = int(value)
                      except ValueError:
                          # Shouldn't ever happen, but could with invalid
                          # ANSI.
                          continue
                      else:
                          fg_color = _ansi_code_to_color.get(value - 30)
                          bg_color = _ansi_code_to_color.get(value - 40)
                          if fg_color:
                              self.fg_color = fg_color
                          elif bg_color:
                              self.bg_color = bg_color
                          elif value == 1:
                              self.bold = True
                          elif value == 22:
                              self.bold = False
                          elif value == 39:
                              self.fg_color = None
                          elif value == 49:
                              self.bg_color = None
                          elif value == 0:
                              self.reset_state()
  
      yield match.start(), self.current_token, text
  
file_path: datalad/docs/utils/pygments_ansi_color.py
imports: from __future__ import absolute_import
  from __future__ import unicode_literals
  import itertools
  import re
  import pygments.lexer
  import pygments.token
label_desc: Use image node_id 4 for calling the AnsiColorLexer obj's underlying member method code with example usage: obj.process(match) without return types