From a2338e4838223ed9c65397eba57f6fd14e1a062f Mon Sep 17 00:00:00 2001 From: jfbu Date: Fri, 10 Feb 2017 14:35:58 +0100 Subject: [PATCH] If ``:start-after:`` is used, make ``:lines:`` relative (close: #3412) --- doc/markup/code.rst | 21 +++++-- sphinx/directives/code.py | 56 ++++++++++--------- .../test-directive-code/lineno_match.rst | 6 ++ tests/test_directive_code.py | 6 ++ 4 files changed, 57 insertions(+), 32 deletions(-) diff --git a/doc/markup/code.rst b/doc/markup/code.rst index ff0f692fa..677deb30f 100644 --- a/doc/markup/code.rst +++ b/doc/markup/code.rst @@ -182,13 +182,24 @@ Includes ``start-after`` is given as a string option, only lines that follow the first line containing that string are included. If ``end-before`` is given as a string option, only lines that precede the first lines containing that string - are included. If used in combination with ``lines``, make sure the latter - allows the lines (whose count start at ``1`` at top of file) containing the - looked-for strings. + are included. + + With lines selected this way it is still possible to use ``lines``, the + numbers being now interpreted relative to the already selected lines. + + .. versionchanged:: 1.5.3 + Formerly, ``lines`` still referred to the included file, and it was + needed that those lines containing the requested strings were among + the allowed ones. + + When lines have been selected in any of the ways described above, the + line numbers in ``emphasize-lines`` refer to the selection, with the + line count starting at ``1``. When specifying particular parts of a file to display, it can be useful to - display exactly which lines are being presented. - This can be done using the ``lineno-match`` option. + display the original line numbers. This can be done using the + ``lineno-match`` option, which is however allowed only when the selection + consists of contiguous lines. You can prepend and/or append a line to the included code, using the ``prepend`` and ``append`` option, respectively. This is useful e.g. for diff --git a/sphinx/directives/code.py b/sphinx/directives/code.py index 3aeb98640..c9d073abd 100644 --- a/sphinx/directives/code.py +++ b/sphinx/directives/code.py @@ -270,31 +270,6 @@ class LiteralInclude(Directive): if 'lineno-match' in self.options: linenostart = tags[objectname][1] - linespec = self.options.get('lines') - if linespec: - try: - linelist = parselinenos(linespec, len(lines)) - except ValueError as err: - return [document.reporter.warning(str(err), line=self.lineno)] - - if 'lineno-match' in self.options: - # make sure the line list is not "disjoint". - previous = linelist[0] - for line_number in linelist[1:]: - if line_number == previous + 1: - previous = line_number - continue - return [document.reporter.warning( - 'Cannot use "lineno-match" with a disjoint set of ' - '"lines"', line=self.lineno)] - linenostart = linelist[0] + 1 - # just ignore non-existing lines - lines = [lines[i] for i in linelist if i < len(lines)] - if not lines: - return [document.reporter.warning( - 'Line spec %r: no lines pulled from include file %r' % - (linespec, filename), line=self.lineno)] - linespec = self.options.get('emphasize-lines') if linespec: try: @@ -320,10 +295,12 @@ class LiteralInclude(Directive): for line_number, line in enumerate(lines): if not use and start_str and start_str in line: if 'lineno-match' in self.options: - linenostart += line_number + 1 - use = True + linenostart = line_number + 1 if start_inclusive: res.append(line) + else: + linenostart +=1 + use = True elif use and end_str and end_str in line: if end_inclusive: res.append(line) @@ -332,6 +309,31 @@ class LiteralInclude(Directive): res.append(line) lines = res + linespec = self.options.get('lines') + if linespec: + try: + linelist = parselinenos(linespec, len(lines)) + except ValueError as err: + return [document.reporter.warning(str(err), line=self.lineno)] + + if 'lineno-match' in self.options: + # make sure the line list is not "disjoint". + previous = linelist[0] + for line_number in linelist[1:]: + if line_number == previous + 1: + previous = line_number + continue + return [document.reporter.warning( + 'Cannot use "lineno-match" with a disjoint set of ' + '"lines"', line=self.lineno)] + linenostart += linelist[0] + # just ignore non-existing lines + lines = [lines[i] for i in linelist if i < len(lines)] + if not lines: + return [document.reporter.warning( + 'Line spec %r: no lines pulled from include file %r' % + (linespec, filename), line=self.lineno)] + prepend = self.options.get('prepend') if prepend: lines.insert(0, prepend + '\n') diff --git a/tests/roots/test-directive-code/lineno_match.rst b/tests/roots/test-directive-code/lineno_match.rst index 42987609a..b200a21bb 100644 --- a/tests/roots/test-directive-code/lineno_match.rst +++ b/tests/roots/test-directive-code/lineno_match.rst @@ -16,6 +16,12 @@ Literal Includes with Line Numbers Matching :start-after: pass :lineno-match: +.. literalinclude:: literal.inc + :language: python + :start-after: Literally + :lines: 1,2 + :lineno-match: + .. literalinclude:: literal.inc :language: python :start-at: class Bar: diff --git a/tests/test_directive_code.py b/tests/test_directive_code.py index 4ebe937d8..b87f23a63 100644 --- a/tests/test_directive_code.py +++ b/tests/test_directive_code.py @@ -223,6 +223,12 @@ def test_literal_include_lineno_match(app, status, warning): '14') assert start_after in html + start_after_with_lines = ( + '
'
+        '2\n'
+        '3
') + assert start_after_with_lines in html + start_at_end_at = ( '
'
         ' 9\n'