docs: def cursor(
      belstr: str, ast: AST, cursor_loc: int, result: Mapping[str, Any] = None
  ) -> Mapping[str, Any]:
      """Find BEL function or argument at cursor location
  
      Args:
          belstr: BEL String used to create the completion_text
          ast (Mapping[str, Any]): AST (dict) of BEL String
          cursor_loc (int): given cursor location from input field
              cursor_loc starts at 0, think of it like a block cursor covering each char
          result: used to recursively return the result
      Returns:
          result dict
      """
  
      log.debug(f"SubAST: {json.dumps(ast, indent=4)}")
  
      # Recurse down through subject, object, nested to functions
      log.debug(f"Cursor keys {ast.keys()}, BELStr: {belstr}")
  
      if len(belstr) == 0:
          return {"type": "Function", "replace_span": (0, 0), "completion_text": ""}
  
      if "relation" in ast and in_span(cursor_loc, ast["relation"]["span"]):
          log.debug("In relation")
  
          completion_text = belstr[ast["relation"]["span"][0] : cursor_loc + 1]
          return {
              "type": "Relation",
              "replace_span": ast["relation"]["span"],
              "completion_text": completion_text,
          }
  
      # Handle subject, object and nested keys in tree
      elif "span" not in ast and isinstance(ast, dict):
          for key in ast:
              if key in ["subject", "object", "nested"]:
                  log.debug(f"Recursing Keys {key}")
                  result = cursor(belstr, ast[key], cursor_loc, result=result)
                  if result:
                      return result
  
      # Matches Functions, NSArgs and StrArgs/StrArgNSArg
      if "span" in ast and in_span(cursor_loc, ast["span"]):
          log.debug("Inside subject/object subAST")
          if "function" in ast:
              name_span = ast["function"]["name_span"]
              if in_span(cursor_loc, name_span):
                  return {
                      "type": "Function",
                      "replace_span": name_span,
                      "completion_text": belstr[name_span[0] : cursor_loc + 1],
                  }
              for idx, arg in enumerate(ast["args"]):
                  if (
                      cursor_loc == ast["function"]["parens_span"][0]
                      and ast["function"]["parens_span"][1] == -1
                  ):
                      return {
                          "type": "StrArg",  # default type if unknown
                          "arg_idx": idx,
                          "replace_span": arg["span"],  # replace entire strarg
                          "parent_function": ast["function"]["name"],
                          "completion_text": "",
                      }
  
                  elif in_span(cursor_loc, arg["span"]):
                      log.debug(
                          f'In argument span {arg["span"]}  Cursor_loc: {cursor_loc}'
                      )
                      if arg["type"] == "Function":
                          if in_span(cursor_loc, arg["function"]["name_span"]):
                              log.debug("Found replace_span in args: Function type")
                              return {
                                  "type": "Function",
                                  "replace_span": arg["function"][
                                      "name_span"
                                  ],  # replace function name only
                                  "arg_idx": idx,
                                  "args": copy.deepcopy(ast["args"]),
                                  "parent_function": ast["function"]["name"],
                                  "completion_text": belstr[
                                      arg["function"]["name_span"][0] : cursor_loc + 1
                                  ],
                              }
                          else:
                              log.debug(f'Recursing Function  {arg["span"]}')
                              result = cursor(belstr, arg, cursor_loc, result=result)
                      elif arg["type"] == "NSArg":
  
                          result = {
                              "type": "NSArg",
                              "replace_span": arg["span"],  # replace entire nsarg
                              "arg_idx": idx,
                              "args": copy.deepcopy(ast["args"]),
                              "parent_function": ast["function"]["name"],
                          }
  
                          # Filter on namespace and query on ns_val chars up to cursor_loc
                          if in_span(cursor_loc, arg["nsarg"]["ns_val_span"]):
                              result["namespace"] = arg["nsarg"][
                                  "ns"
                              ]  # provide namespace for nsarg filtering
                              result["completion_text"] = belstr[
                                  arg["nsarg"]["ns_val_span"][0] : cursor_loc + 1
                              ]
                          # Query on nsarg chars up to cursor_loc
                          else:
                              result["completion_text"] = belstr[
                                  arg["nsarg"]["ns_span"][0] : cursor_loc + 1
                              ]
  
                          log.debug(f"Found replace_span in args: NSArg {result}")
                          return result
                      elif (
                          arg["type"] == "StrArg"
                      ):  # in case this is a default namespace StrArg
                          if (
                              arg["span"][0] == arg["span"][1]
                          ):  # handle case like p() cursor=2
                              completion_text = arg["arg"]
                          else:
                              completion_text = belstr[arg["span"][0] : cursor_loc + 1]
  
                          return {
                              "type": "StrArg",
                              "arg_idx": idx,
                              "replace_span": arg["span"],  # replace entire strarg
                              "parent_function": ast["function"]["name"],
                              "completion_text": completion_text.lstrip(),
                          }
      return result