class_docstr: Read notebook cells from R scripts written according
  to the knitr-spin syntax
class_docstr_tok: ["Read","notebook","cells","from","R","scripts","written","according","to","the","knitr-spin","syntax"]
docstr: Return position of end of cell marker, and position
  of first line after cell
docstr_tok: ["Return","position","of","end","of","cell","marker",",","and","position","of","first","line","after","cell"]
code: def find_cell_end(self, lines):
      """Return position of end of cell marker, and position
      of first line after cell"""
      if self.metadata is None and lines[0].startswith("#'"):
          self.cell_type = "markdown"
          for i, line in enumerate(lines):
              if not line.startswith("#'"):
                  if _BLANK_LINE.match(line):
                      return i, i + 1, False
                  return i, i, False
  
          return len(lines), len(lines), False
  
      if self.metadata and "cell_type" in self.metadata:
          self.cell_type = self.metadata.pop("cell_type")
      else:
          self.cell_type = "code"
  
      parser = StringParser(self.language or self.default_language)
      for i, line in enumerate(lines):
          # skip cell header
          if self.metadata is not None and i == 0:
              continue
  
          if parser.is_quoted():
              parser.read_line(line)
              continue
  
          parser.read_line(line)
  
          if self.start_code_re.match(line) or (
              self.markdown_prefix
              and line.startswith(self.markdown_prefix)
          ):
              if i > 0 and _BLANK_LINE.match(lines[i - 1]):
                  if i > 1 and _BLANK_LINE.match(lines[i - 2]):
                      return i - 2, i, False
                  return i - 1, i, False
              return i, i, False
  
          if _BLANK_LINE.match(line):
              if not next_code_is_indented(lines[i:]):
                  if i > 0:
                      return i, i + 1, False
                  if len(lines) > 1 and not _BLANK_LINE.match(lines[1]):
                      return 1, 1, False
                  return 1, 2, False
  
      return len(lines), len(lines), False
  
imports: import re
  import warnings
  from copy import copy
  from nbformat.v4.nbbase import new_code_cell, new_markdown_cell, new_raw_cell
  from packaging.version import parse
  from .doxygen import doxygen_to_markdown
  from .languages import _SCRIPT_EXTENSIONS
  from .cell_metadata import is_active, is_json_metadata, rmd_options_to_metadata, text_to_metadata
  from .languages import _JUPYTER_LANGUAGES_LOWER_AND_UPPER
  from .magics import is_magic, need_explicit_marker, uncomment_magic, unescape_code_start
  from .pep8 import pep8_lines_between_cells
  from .stringparser import StringParser
label_desc: Use image node_id 2 for calling the RScriptCellReader obj's underlying member method code with example usage: obj.find_cell_end(lines) and returns: len,  len,  False, len,  len,  False, i,  i,  False, i,  i,  False, unknown,  i,  False, int,  int,  False, i,  unknown,  False, unknown,  i,  False, i,  unknown,  False, int,  int,  False