docs: def todo(self, p_identifier):
          """
          The _todos list has the same order as in the backend store (usually
          a todo.txt file. The user refers to the first task as number 1, so use
          index 0, etc.
  
          Alternative ways to identify a todo is using a hashed version based on
          the todo's text, or a regexp that matches the todo's source. The regexp
          match is a fallback.
  
          Returns None when the todo couldn't be found.
          """
          result = None
  
          def todo_by_uid(p_identifier):
              """ Returns the todo that corresponds to the unique ID. """
              result = None
  
              if config().identifiers() == 'text':
                  try:
                      result = self._id_todo_map[p_identifier]
                  except KeyError:
                      pass  # we'll try something else
  
              return result
  
          def todo_by_linenumber(p_identifier):
              """
              Attempts to find the todo on the given line number.
  
              When the identifier is a number but has leading zeros, the result
              will be None.
              """
              result = None
  
              if config().identifiers() != 'text':
                  try:
                      if re.match('[1-9]\d*', p_identifier):
                          # the expression is a string and no leading zeroes,
                          # treat it as an integer
                          raise TypeError
                  except TypeError as te:
                      try:
                          result = self._todos[int(p_identifier) - 1]
                      except (ValueError, IndexError):
                          raise InvalidTodoException from te
  
              return result
  
          def todo_by_regexp(p_identifier):
              """
              Returns the todo that is (uniquely) identified by the given regexp.
              If the regexp matches more than one item, no result is returned.
              """
              result = None
  
              candidates = Filter.GrepFilter(p_identifier).filter(self._todos)
  
              if len(candidates) == 1:
                  result = candidates[0]
              else:
                  raise InvalidTodoException
  
              return result
  
          result = todo_by_uid(p_identifier)
  
          if not result:
              result = todo_by_linenumber(p_identifier)
  
          if not result:
              # convert integer to text so we pass on a valid regex
              result = todo_by_regexp(str(p_identifier))
  
          return result