docs: def parse_raw_fact(raw_fact):
      """
      Extract semantically meaningful sub-components from a ``raw fact`` text.
  
      Args:
          raw_fact (text_type): ``raw fact`` text to be parsed.
  
      Returns:
          dict: dict with sub-components as values.
      """
      def at_split(string):
          """
          Return everything in front of the (leftmost) '@'-symbol, if it was used.
  
          Args:
              string (str):  The string to be parsed.
  
          Returns:
              tuple: (front, back) representing the substrings before and after the
                  most left ``@`` symbol. If no such symbol was present at all,
                  ``back=None``. Both substrings have been trimmed of any leading
                  and trailing whitespace.
  
          Note:
              If our string contains multiple ``@`` symbols, all but the most left
              one will be treated as part of the regular ``back`` string.
              This allows for usage of the symbol in descriptions, categories and tags.
  
              Also note that *no tags are extracted* any tags included will be considered
              part of the ``category`` string. We are likely to remove this parsing function
              in ``0.14.0`` in favour of a regex based solution so we will not spend
              time on tags for now
          """
          result = string.split('@', 1)
          length = len(result)
          if length == 1:
              front, back = result[0].strip(), None
          else:
              front, back = result
              front, back = front.strip(), back.strip()
          return (front, back)
  
      def comma_split(string):
          """
          Split string at the most left comma.
  
          Args:
              string (str): String to be processed. At this stage this should
                  look something like ``<Category> and <tags>, <Description>
  
  
          Returns
              tuple: (category_and_tags, description). Both substrings have their
                  leading/trailing whitespace removed.
                  ``category_and_tags`` may include >=0 tags indicated by a leading ``#``.
                  As we have used the most left ``,`` to separate both substrings that
                  means that categories and tags can not contain any ``,`` but the
                  description text may contain as many as wished.
          """
  
          result = string.split(',', 1)
          length = len(result)
          if length == 1:
              category, description = result[0].strip(), None
          else:
              category, description = tuple(result)
              category, description = category.strip(), description.strip()
          return (category.strip(), description)
  
      time_info, rest = time_helpers.extract_time_info(raw_fact)
      activity_name, back = at_split(rest)
  
      if back:
          category_name, description = comma_split(back)
      else:
          category_name, description = None, None
  
      return {
          'timeinfo': time_info,
          'category': category_name,
          'activity': activity_name,
          'description': description,
      }