2
2
3
3
import os
4
4
from itertools import groupby , count
5
- from operator import itemgetter
6
5
import json
7
6
8
- import sphinx
9
- from sphinx .util import logging
7
+ from sphinx .util import logging , parselinenos
10
8
from sphinx .util .fileutil import copy_asset
11
9
from sphinx .transforms import SphinxTransform
12
10
from sphinx .errors import ExtensionError
26
24
27
25
import nbformat
28
26
29
- from ipywidgets import Widget
30
27
import ipywidgets .embed
31
28
32
29
from ._version import __version__
@@ -136,6 +133,8 @@ class JupyterCell(Directive):
136
133
If provided, the code will be shown below the cell output.
137
134
linenos : bool
138
135
If provided, the code will be shown with line numbering.
136
+ emphasize-lines : comma separated list of line numbers
137
+ If provided, the specified lines will be highlighted.
139
138
raises : comma separated list of exception types
140
139
If provided, a comma-separated list of exception type names that
141
140
the cell may raise. If one of the listed execption types is raised
@@ -159,11 +158,14 @@ class JupyterCell(Directive):
159
158
'hide-output' : directives .flag ,
160
159
'code-below' : directives .flag ,
161
160
'linenos' : directives .flag ,
161
+ 'emphasize-lines' : directives .unchanged_required ,
162
162
'raises' : csv_option ,
163
163
'stderr' : directives .flag ,
164
164
}
165
165
166
166
def run (self ):
167
+ location = self .state_machine .get_source_and_line (self .lineno )
168
+
167
169
if self .arguments :
168
170
# As per 'sphinx.directives.code.LiteralInclude'
169
171
env = self .state .document .settings .env
@@ -172,7 +174,7 @@ def run(self):
172
174
if self .content :
173
175
logger .warning (
174
176
'Ignoring inline code in Jupyter cell included from "{}"'
175
- .format (rel_filename )
177
+ .format (rel_filename ), location = location
176
178
)
177
179
try :
178
180
with open (filename ) as f :
@@ -194,8 +196,10 @@ def run(self):
194
196
hide_output = ('hide-output' in self .options ),
195
197
code_below = ('code-below' in self .options ),
196
198
linenos = ('linenos' in self .options ),
199
+ emphasize_lines = self .options .get ('emphasize-lines' ),
197
200
raises = self .options .get ('raises' ),
198
201
stderr = ('stderr' in self .options ),
202
+ _location = location ,
199
203
)]
200
204
201
205
@@ -408,12 +412,26 @@ def apply(self):
408
412
linenostart = 1
409
413
for node in nodes :
410
414
source = node .children [0 ]
415
+ nlines = source .rawsource .count ("\n " ) + 1
416
+
411
417
if linenos_config or continue_linenos or node ["linenos" ]:
412
418
source ["linenos" ] = True
413
- if continue_linenos :
414
- source ["highlight_args" ] = {'linenostart' : linenostart }
415
- linenostart += source .rawsource .count ("\n " ) + 1
416
419
420
+ highlight_args = source ['highlight_args' ] = {}
421
+
422
+ if continue_linenos :
423
+ highlight_args ['linenostart' ] = linenostart
424
+ linenostart += nlines
425
+
426
+ emphasize_linespec = node ['emphasize_lines' ]
427
+ if emphasize_linespec :
428
+ hl_lines = parselinenos (emphasize_linespec , nlines )
429
+ if any (i >= nlines for i in hl_lines ):
430
+ logger .warning (
431
+ 'Line number spec is out of range(1-{}): {}' .format (
432
+ nlines , emphasize_linespec ), location = node ['_location' ])
433
+ hl_lines = [i + 1 for i in hl_lines if i < nlines ]
434
+ highlight_args ['hl_lines' ] = hl_lines
417
435
418
436
# Add code cell CSS class
419
437
for node in nodes :
0 commit comments