|
13 | 13 | import itertools |
14 | 14 | from os import path |
15 | 15 | import sys |
| 16 | +from pygments.lexers.shell import BashSessionLexer |
16 | 17 |
|
17 | 18 | from docutils import nodes |
18 | 19 |
|
@@ -112,51 +113,54 @@ def __init__(self, *nodes: nodes.Element) -> None: |
112 | 113 |
|
113 | 114 |
|
114 | 115 | class Code(Snippet): |
115 | | - ALLOWED_LANGS = ['console'] |
116 | 116 | #: Language of code block |
117 | 117 | lang: str |
118 | 118 | #: Description of code block, usually the text of preceding paragraph |
119 | 119 | desc: str |
120 | 120 |
|
121 | 121 | def __init__(self, node: nodes.literal_block) -> None: |
122 | 122 | assert isinstance(node, nodes.literal_block) |
123 | | - super().__init__(node) |
124 | 123 |
|
125 | 124 | self.lang = node['language'] |
126 | | - if self.lang not in self.ALLOWED_LANGS: |
| 125 | + if self.lang not in BashSessionLexer.aliases: # TODO: support more language |
127 | 126 | raise ValueError( |
128 | | - f'Language of node {node} {self.lang} not in allowed language list {self.ALLOWED_LANGS}', |
| 127 | + f'Language {self.lang} is not supported', |
129 | 128 | ) |
130 | 129 |
|
131 | 130 | self.desc = '' |
| 131 | + # Use the preceding paragraph as descritpion. We usually write some |
| 132 | + # descritpions before a code block. For example, The ``::`` syntax is |
| 133 | + # a common way to create code block:: |
| 134 | + # |
| 135 | + # | Foo:: | <paragraph> |
| 136 | + # | | Foo: |
| 137 | + # | Bar | <literal_block xml:space="preserve"> |
| 138 | + # | | Bar |
| 139 | + # |
| 140 | + # In this case, the paragraph "Foo:" is the descritpion of the code block. |
| 141 | + # This convention also applies to the code, code-block, sourcecode directive. |
132 | 142 | if isinstance(para := node.previous_sibling(), nodes.paragraph): |
133 | | - # Use the preceding paragraph as descritpion. |
134 | | - # |
135 | | - # We usually write some descritpions before a code block, for example, |
136 | | - # The ``::`` syntax is a common way to create code block:: |
137 | | - # |
138 | | - # | Foo:: | <paragraph> |
139 | | - # | | Foo: |
140 | | - # | Bar | <literal_block xml:space="preserve"> |
141 | | - # | | Bar |
142 | | - # |
143 | | - # In this case, the preceding paragraph "Foo:" is the descritpion |
144 | | - # of the code block. This convention also applies to the code, |
145 | | - # code-block, sourcecode directive. |
146 | | - |
147 | 143 | # For better display, the trailing colon is removed. |
148 | 144 | # TODO: https://en.wikipedia.org/wiki/Colon_(punctuation)#Computing |
149 | 145 | self.desc += para.astext().replace('\n', ' ').rstrip(':::︁︓﹕') |
150 | 146 | if caption := node.get('caption'): |
151 | 147 | # Use caption as descritpion. |
152 | | - # In sphinx, all of code-block, sourcecode and code have caption option. |
| 148 | + # All of code-block, sourcecode and code directives have caption option. |
153 | 149 | # https://www.sphinx-doc.org/en/master/usage/restructuredtext/directives.html#directive-code-block |
154 | 150 | self.desc += caption |
155 | 151 | if not self.desc: |
156 | 152 | raise ValueError( |
157 | 153 | f'Node f{node} lacks description: a preceding paragraph or a caption' |
158 | 154 | ) |
159 | 155 |
|
| 156 | + if isinstance(para, nodes.paragraph): |
| 157 | + # If we have a paragraph preceding code block, include it. |
| 158 | + super().__init__(para, node) |
| 159 | + # Fixup text field, it should be pure code. |
| 160 | + self.text = node.astext().split('\n') |
| 161 | + else: |
| 162 | + super().__init__(node) |
| 163 | + |
160 | 164 |
|
161 | 165 | class WithTitle(object): |
162 | 166 | title: str |
|
0 commit comments