Skip to content

Commit 714b6f1

Browse files
committed
Add a pip-cli directive for MyST
1 parent 6b076e5 commit 714b6f1

File tree

1 file changed

+81
-1
lines changed

1 file changed

+81
-1
lines changed

docs/pip_sphinxext.py

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
"""pip sphinx extensions"""
22

33
import optparse
4+
import re
45
import sys
56
from textwrap import dedent
67

78
from docutils import nodes
89
from docutils.parsers import rst
9-
from docutils.statemachine import ViewList
10+
from docutils.statemachine import StringList, ViewList
1011

1112
from pip._internal.cli import cmdoptions
1213
from pip._internal.commands import commands_dict, create_command
@@ -147,6 +148,84 @@ def process_options(self):
147148
)
148149

149150

151+
class PipCLIDirective(rst.Directive):
152+
"""
153+
- Only works when used in a MyST document.
154+
- Requires sphinx-inline-tabs' tab directive.
155+
"""
156+
157+
has_content = True
158+
optional_arguments = 1
159+
160+
def run(self):
161+
node = nodes.paragraph()
162+
node.document = self.state.document
163+
164+
os_variants = {
165+
"Linux": {
166+
"highlighter": "console",
167+
"executable": "python",
168+
"prompt": "$",
169+
},
170+
"MacOS": {
171+
"highlighter": "console",
172+
"executable": "python",
173+
"prompt": "$",
174+
},
175+
"Windows": {
176+
"highlighter": "doscon",
177+
"executable": "py",
178+
"prompt": "C:>",
179+
},
180+
}
181+
182+
if self.arguments:
183+
assert self.arguments == ["in-a-venv"]
184+
in_virtual_environment = True
185+
else:
186+
in_virtual_environment = False
187+
188+
lines = []
189+
# Create a tab for each OS
190+
for os, variant in os_variants.items():
191+
192+
# Unpack the values
193+
prompt = variant["prompt"]
194+
highlighter = variant["highlighter"]
195+
if in_virtual_environment:
196+
executable = "python"
197+
pip_spelling = "pip"
198+
else:
199+
executable = variant["executable"]
200+
pip_spelling = f"{executable} -m pip"
201+
202+
# Substitute the various "prompts" into the correct variants
203+
substitution_pipeline = [
204+
(
205+
r"(^|(?<=\n))\$ python",
206+
f"{prompt} {executable}",
207+
),
208+
(
209+
r"(^|(?<=\n))\$ pip",
210+
f"{prompt} {pip_spelling}",
211+
),
212+
]
213+
content = self.block_text
214+
for pattern, substitution in substitution_pipeline:
215+
content = re.sub(pattern, substitution, content)
216+
217+
# Write the tab
218+
lines.append(f"````{{tab}} {os}")
219+
lines.append(f"```{highlighter}")
220+
lines.append(f"{content}")
221+
lines.append("```")
222+
lines.append("````")
223+
224+
string_list = StringList(lines)
225+
self.state.nested_parse(string_list, 0, node)
226+
return [node]
227+
228+
150229
def setup(app):
151230
app.add_directive("pip-command-usage", PipCommandUsage)
152231
app.add_directive("pip-command-description", PipCommandDescription)
@@ -156,3 +235,4 @@ def setup(app):
156235
app.add_directive(
157236
"pip-requirements-file-options-ref-list", PipReqFileOptionsReference
158237
)
238+
app.add_directive("pip-cli", PipCLIDirective)

0 commit comments

Comments
 (0)