1
1
"""pip sphinx extensions"""
2
2
3
3
import optparse
4
+ import re
4
5
import sys
5
6
from textwrap import dedent
6
7
7
8
from docutils import nodes
8
9
from docutils .parsers import rst
9
- from docutils .statemachine import ViewList
10
+ from docutils .statemachine import StringList , ViewList
10
11
11
12
from pip ._internal .cli import cmdoptions
12
13
from pip ._internal .commands import commands_dict , create_command
@@ -147,6 +148,84 @@ def process_options(self):
147
148
)
148
149
149
150
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
+
150
229
def setup (app ):
151
230
app .add_directive ("pip-command-usage" , PipCommandUsage )
152
231
app .add_directive ("pip-command-description" , PipCommandDescription )
@@ -156,3 +235,4 @@ def setup(app):
156
235
app .add_directive (
157
236
"pip-requirements-file-options-ref-list" , PipReqFileOptionsReference
158
237
)
238
+ app .add_directive ("pip-cli" , PipCLIDirective )
0 commit comments