Repository: sphinx-doc/sphinx

Issue:
:end-before improvement for literalinclude
With `literalinclude`, `:end-before:` would be more useful if started matching *after* the first line of the block so that it doesn't generate an empty block.

Illustration:

My input file has the usual ini file syntax, and I want to quote one section in the page. (Similar examples would include quoting one class or struct from a source file containing several class/struct definitions, or generally, quoting from one delimiter line up to the next similar delimiter line). The input file:

```
# file someconfig.ini
[Config Foo]
one = 111
two = 5543
three = 23

[Config Bar]
four = 444
etc = 345
```

And the document source:

```
.. literalinclude:: someconfig.ini
   :start-at: Config Foo
   :end-before: Config
```

Currently it produces an empty block because `:end-before:` matches immediately, but it would be much better if it stopped at the `[Config Bar]` line and included the whole `Foo` section. The current behavior is not that useful (who wants to purposefully add an empty block in the output?)



Discussion:
codecov[bot]: # [Codecov](https://codecov.io/gh/sphinx-doc/sphinx/pull/6748?src=pr&el=h1) Report
> Merging [#6748](https://codecov.io/gh/sphinx-doc/sphinx/pull/6748?src=pr&el=desc) into [2.0](https://codecov.io/gh/sphinx-doc/sphinx/commit/314e12ca148e91bc994678d2b2010f984999f7c2?src=pr&el=desc) will **increase** coverage by `<.01%`.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/sphinx-doc/sphinx/pull/6748/graphs/tree.svg?width=650&token=VFlFSELbkw&height=150&src=pr)](https://codecov.io/gh/sphinx-doc/sphinx/pull/6748?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##              2.0    #6748      +/-   ##
==========================================
+ Coverage   83.72%   83.73%   +<.01%     
==========================================
  Files         271      271              
  Lines       41149    41155       +6     
  Branches     6010     6010              
==========================================
+ Hits        34452    34460       +8     
+ Misses       5366     5365       -1     
+ Partials     1331     1330       -1
```


| [Impacted Files](https://codecov.io/gh/sphinx-doc/sphinx/pull/6748?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [sphinx/directives/code.py](https://codecov.io/gh/sphinx-doc/sphinx/pull/6748/diff?src=pr&el=tree#diff-c3BoaW54L2RpcmVjdGl2ZXMvY29kZS5weQ==) | `86.78% <100%> (+0.76%)` | :arrow_up: |
| [tests/test\_directive\_code.py](https://codecov.io/gh/sphinx-doc/sphinx/pull/6748/diff?src=pr&el=tree#diff-dGVzdHMvdGVzdF9kaXJlY3RpdmVfY29kZS5weQ==) | `100% <100%> (ø)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/sphinx-doc/sphinx/pull/6748?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/sphinx-doc/sphinx/pull/6748?src=pr&el=footer). Last update [314e12c...519898f](https://codecov.io/gh/sphinx-doc/sphinx/pull/6748?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/CHANGES b/CHANGES
index 33d5ff2b5..9fdf32f0b 100644
--- a/CHANGES
+++ b/CHANGES
@@ -7,6 +7,9 @@ Dependencies
 Incompatible changes
 --------------------
 
+* #6742: ``end-before`` option of :rst:dir:`literalinclude` directive does not
+  match the first line of the code block.
+
 Deprecated
 ----------
 
diff --git a/sphinx/directives/code.py b/sphinx/directives/code.py
index aa5192f78..3bcfb917f 100644
--- a/sphinx/directives/code.py
+++ b/sphinx/directives/code.py
@@ -348,7 +348,7 @@ def end_filter(self, lines: List[str], location: Tuple[str, int] = None) -> List
                         return lines[:lineno + 1]
                     else:
                         if lineno == 0:
-                            return []
+                            pass  # end-before ignores first line
                         else:
                             return lines[:lineno]
             if inclusive is True:


Test patch:
diff --git a/tests/test_directive_code.py b/tests/test_directive_code.py
index 13b451078..ecf5423c2 100644
--- a/tests/test_directive_code.py
+++ b/tests/test_directive_code.py
@@ -206,6 +206,14 @@ def test_LiteralIncludeReader_missing_start_and_end(literal_inc_path):
         content, lines = reader.read()
 
 
+def test_LiteralIncludeReader_end_before(literal_inc_path):
+    options = {'end-before': 'nclud'}  # *nclud* matches first and third lines.
+    reader = LiteralIncludeReader(literal_inc_path, options, DUMMY_CONFIG)
+    content, lines = reader.read()
+    assert content == ("# Literally included file using Python highlighting\n"
+                       "\n")
+
+
 @pytest.mark.xfail(os.name != 'posix', reason="Not working on windows")
 def test_LiteralIncludeReader_prepend(literal_inc_path):
     options = {'lines': '1', 'prepend': 'Hello', 'append': 'Sphinx'}