Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for syntax highlighting in PEPs #1638

Closed
wants to merge 6 commits into from

Conversation

hugovk
Copy link
Member

@hugovk hugovk commented Sep 21, 2020

This is the same as @ilevkivskyi's #1063: rebased with conflicts resolved.

It was closed in June 2017 because the plan was to get the PEPs onto Read the Docs (#1063 (comment)).

In December 2017 @brettcannon suggested (#1063 (comment)):

Maybe we should open this again since getting the PEPs over to Read the Docs is moving at the speed of mud?

Three years on: I agree, it'd be great get colouring in whilst waiting on RtD (this big recent effort has stalled: python/peps#1385). I find highlighted code much easier to read.

Refs:

Comment on lines 22 to 27
# To simplify syntax highlighting, all literal blocks (those produced by ::)
# in the following PEPs will be automatically highlighted using Python lexer.
# PEP editors/authors could make simple PRs extending this list.
# This will be not needed when PEPs are moved to RtD and all code blocks are
# formatted using .. code:: language.
PURE_PYTHON_PEPS = [483, 484, 526]
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like it would make more sense to update the PEPs with appropriate code blocks rather than do this. I think this would also remove the need for the following lines (although I'm not sure what "Fix highlighting code" is currently doing.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, I'll comment below what's happening.

Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is no longer used.

Comment on lines 22 to 27
# To simplify syntax highlighting, all literal blocks (those produced by ::)
# in the following PEPs will be automatically highlighted using Python lexer.
# PEP editors/authors could make simple PRs extending this list.
# This will be not needed when PEPs are moved to RtD and all code blocks are
# formatted using .. code:: language.
PURE_PYTHON_PEPS = [483, 484, 526]
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, I'll comment below what's happening.

@@ -140,6 +150,21 @@ def convert_pep_page(pep_number, content):
# Fix PEP links
pep_content = BeautifulSoup(data['content'], 'lxml')
body_links = pep_content.find_all("a")
# Fix highlighting code
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This chunk (from here to the next comment) is dealing with blocks with an explicit language, such as .. code-block:: python or .. code-block:: c.

More detail: the generated PEPs from https://github.com/python/peps has HTML like for these:

<pre class="code python literal-block">
...
<pre class="code c literal-block">

And with no language specified (::) have:

<pre class="literal-block">

This chunk finds all <pre class="code ...">, deletes those classes from the pre, and wraps them in a <div class="highlight"> for later processing.

div = pep_content.new_tag('div')
div['class'] = ['highlight']
cb.wrap(div)
# Highlight existing pure-Python PEPs
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This chunk is dealing with blocks that don't have an explicit language, those marked with ::, and defaulting to Python.

This PR is being cautious and only defaulting to Python for PURE_PYTHON_PEPS.

More detail:

It finds all <pre class="literal-block"> (the language-specific ones have just had their literal-block removed), then puts it through the Python highlighter.


I think it'd be good to default to Python for all :: blocks, and we can specify the language in the actual PEPs for non-Python :: blocks.

Sphinx also defaults to Python*, so this will also help for when Sphinx/RtD stuff is ready, and avoid us needing to replace :: with .. code-block:: python.

* Sphinx defaults to Python unless a directive like highlight:: c is used. The PEPs don't use highlight:: so we're good.

@hugovk
Copy link
Member Author

hugovk commented Sep 22, 2020

Some example code.

pep-0526.txt

PEP: 526
Title: Syntax for Variable Annotations
Version: $Revision$
Last-Modified: $Date$
Author: <snip>
Status: Final
Type: Standards Track
Content-Type: text/x-rst
Created: 09-Aug-2016
Python-Version: 3.6
Post-History: 30-Aug-2016, 02-Sep-2016
Resolution: https://mail.python.org/pipermail/python-dev/2016-September/146282.html


TODO DEFAULT::

  # Should be a comment in Python
  #include <stdlib.h>

  # 'primes' is a list of integers
  primes = []  # type: List[int]

  # 'captain' is a string (Note: initial value is a problem)
  captain = ...  # type: str

  class Starship:
      # 'stats' is a class variable
      stats = {}  # type: Dict[str, int]


TODO PYTHON:

.. code-block:: python

  # Should be a comment in Python
  #include <stdlib.h>

  # 'primes' is a list of integers
  primes = []  # type: List[int]

  # 'captain' is a string (Note: initial value is a problem)
  captain = ...  # type: str

  class Starship:
      # 'stats' is a class variable
      stats = {}  # type: Dict[str, int]


TODO C:

.. code-block:: c

    #include <stdlib.h>

    size_t alloc_padding = 2;
    size_t arena_padding = 10;

    void* my_malloc(void *ctx, size_t size)
    {
        int padding = *(int *)ctx;
        return malloc(size + padding);
    }

Output of make pep-0526.html

<!--
This HTML is auto-generated.  DO NOT EDIT THIS FILE!  If you are writing a new
PEP, see http://www.python.org/dev/peps/pep-0001 for instructions and links
to templates.  DO NOT USE THIS HTML FILE AS YOUR TEMPLATE!
-->
<table class="rfc2822 docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">PEP:</th><td class="field-body">526</td>
</tr>
<tr class="field"><th class="field-name">Title:</th><td class="field-body">Syntax for Variable Annotations</td>
</tr>
<tr class="field"><th class="field-name">Version:</th><td class="field-body">$Revision$</td>
</tr>
<tr class="field"><th class="field-name">Last-Modified:</th><td class="field-body"><a class="reference external" href="https://hg.python.org/peps/file/tip/pep-0526.txt">$Date$</a></td>
</tr>
<tr class="field"><th class="field-name">Author:</th><td class="field-body">&lt;snip&gt;</td>
</tr>
<tr class="field"><th class="field-name">Status:</th><td class="field-body">Final</td>
</tr>
<tr class="field"><th class="field-name">Type:</th><td class="field-body">Standards Track</td>
</tr>
<tr class="field"><th class="field-name">Content-Type:</th><td class="field-body"><a class="reference external" href="/dev/peps/pep-0012">text/x-rst</a></td>
</tr>
<tr class="field"><th class="field-name">Created:</th><td class="field-body">09-Aug-2016</td>
</tr>
<tr class="field"><th class="field-name">Python-Version:</th><td class="field-body">3.6</td>
</tr>
<tr class="field"><th class="field-name">Post-History:</th><td class="field-body">30-Aug-2016, 02-Sep-2016</td>
</tr>
<tr class="field"><th class="field-name">Resolution:</th><td class="field-body"><a class="reference external" href="https://mail.python.org/pipermail/python-dev/2016-September/146282.html">https://mail.python.org/pipermail/python-dev/2016-September/146282.html</a></td>
</tr>
</tbody>
</table>
<hr />
<p>TODO DEFAULT:</p>
<pre class="literal-block">
# Should be a comment in Python
#include &lt;stdlib.h&gt;

# 'primes' is a list of integers
primes = []  # type: List[int]

# 'captain' is a string (Note: initial value is a problem)
captain = ...  # type: str

class Starship:
    # 'stats' is a class variable
    stats = {}  # type: Dict[str, int]
</pre>
<p>TODO PYTHON:</p>
<pre class="code python literal-block">
<span class="comment single"># Should be a comment in Python</span>
<span class="comment single">#include &lt;stdlib.h&gt;</span>

<span class="comment single"># 'primes' is a list of integers</span>
<span class="name">primes</span> <span class="operator">=</span> <span class="punctuation">[]</span>  <span class="comment single"># type: List[int]</span>

<span class="comment single"># 'captain' is a string (Note: initial value is a problem)</span>
<span class="name">captain</span> <span class="operator">=</span> <span class="operator">...</span>  <span class="comment single"># type: str</span>

<span class="keyword">class</span> <span class="name class">Starship</span><span class="punctuation">:</span>
    <span class="comment single"># 'stats' is a class variable</span>
    <span class="name">stats</span> <span class="operator">=</span> <span class="punctuation">{}</span>  <span class="comment single"># type: Dict[str, int]</span>
</pre>
<p>TODO C:</p>
<pre class="code c literal-block">
<span class="comment preproc">#include</span> <span class="comment preprocfile">&lt;stdlib.h&gt;</span><span class="comment preproc">
</span>
<span class="keyword type">size_t</span> <span class="name">alloc_padding</span> <span class="operator">=</span> <span class="literal number integer">2</span><span class="punctuation">;</span>
<span class="keyword type">size_t</span> <span class="name">arena_padding</span> <span class="operator">=</span> <span class="literal number integer">10</span><span class="punctuation">;</span>

<span class="keyword type">void</span><span class="operator">*</span> <span class="name function">my_malloc</span><span class="punctuation">(</span><span class="keyword type">void</span> <span class="operator">*</span><span class="name">ctx</span><span class="punctuation">,</span> <span class="keyword type">size_t</span> <span class="name">size</span><span class="punctuation">)</span>
<span class="punctuation">{</span>
    <span class="keyword type">int</span> <span class="name">padding</span> <span class="operator">=</span> <span class="operator">*</span><span class="punctuation">(</span><span class="keyword type">int</span> <span class="operator">*</span><span class="punctuation">)</span><span class="name">ctx</span><span class="punctuation">;</span>
    <span class="keyword">return</span> <span class="name">malloc</span><span class="punctuation">(</span><span class="name">size</span> <span class="operator">+</span> <span class="name">padding</span><span class="punctuation">);</span>
<span class="punctuation">}</span>
</pre>

Output of convert_pep_page(526, open("peps/tests/peps/pep-0526.html").read())["content"]

<!--
This HTML is auto-generated.  DO NOT EDIT THIS FILE!  If you are writing a new
PEP, see http://www.python.org/dev/peps/pep-0001 for instructions and links
to templates.  DO NOT USE THIS HTML FILE AS YOUR TEMPLATE!
--><table class="rfc2822 docutils field-list" frame="void" rules="none">
<col class="field-name"/>
<col class="field-body"/>
<tbody valign="top">
<tr class="field"><th class="field-name">PEP:</th><td class="field-body">526</td>
</tr>
<tr class="field"><th class="field-name">Title:</th><td class="field-body">Syntax for Variable Annotations</td>
</tr>
<tr class="field"><th class="field-name">Author:</th><td class="field-body">&lt;snip&gt;</td>
</tr>
<tr class="field"><th class="field-name">Status:</th><td class="field-body">Final</td>
</tr>
<tr class="field"><th class="field-name">Type:</th><td class="field-body">Standards Track</td>
</tr>
<tr class="field"><th class="field-name">Created:</th><td class="field-body">09-Aug-2016</td>
</tr>
<tr class="field"><th class="field-name">Python-Version:</th><td class="field-body">3.6</td>
</tr>
<tr class="field"><th class="field-name">Post-History:</th><td class="field-body">30-Aug-2016, 02-Sep-2016</td>
</tr>
<tr class="field"><th class="field-name">Resolution:</th><td class="field-body"><a class="reference external" href="https://mail.python.org/pipermail/python-dev/2016-September/146282.html">https://mail.python.org/pipermail/python-dev/2016-September/146282.html</a></td>
</tr>
</tbody>
</table>
<hr/>
<p>TODO DEFAULT:</p>
<div class="highlight"><pre><span></span><span class="c1"># Should be a comment in Python</span>
<span class="c1">#include &lt;stdlib.h&gt;</span>

<span class="c1"># 'primes' is a list of integers</span>
<span class="n">primes</span> <span class="o">=</span> <span class="p">[]</span>  <span class="c1"># type: List[int]</span>

<span class="c1"># 'captain' is a string (Note: initial value is a problem)</span>
<span class="n">captain</span> <span class="o">=</span> <span class="o">...</span>  <span class="c1"># type: str</span>

<span class="k">class</span> <span class="nc">Starship</span><span class="p">:</span>
    <span class="c1"># 'stats' is a class variable</span>
    <span class="n">stats</span> <span class="o">=</span> <span class="p">{}</span>  <span class="c1"># type: Dict[str, int]</span>
</pre></div>
<p>TODO PYTHON:</p>
<div class="highlight"><pre>
<span class="comment single"># Should be a comment in Python</span>
<span class="comment single">#include &lt;stdlib.h&gt;</span>

<span class="comment single"># 'primes' is a list of integers</span>
<span class="name">primes</span> <span class="operator">=</span> <span class="punctuation">[]</span>  <span class="comment single"># type: List[int]</span>

<span class="comment single"># 'captain' is a string (Note: initial value is a problem)</span>
<span class="name">captain</span> <span class="operator">=</span> <span class="operator">...</span>  <span class="comment single"># type: str</span>

<span class="keyword">class</span> <span class="name class">Starship</span><span class="punctuation">:</span>
    <span class="comment single"># 'stats' is a class variable</span>
    <span class="name">stats</span> <span class="operator">=</span> <span class="punctuation">{}</span>  <span class="comment single"># type: Dict[str, int]</span>
</pre></div>
<p>TODO C:</p>
<div class="highlight"><pre>
<span class="comment preproc">#include</span> <span class="comment preprocfile">&lt;stdlib.h&gt;</span><span class="comment preproc">
</span>
<span class="keyword type">size_t</span> <span class="name">alloc_padding</span> <span class="operator">=</span> <span class="literal number integer">2</span><span class="punctuation">;</span>
<span class="keyword type">size_t</span> <span class="name">arena_padding</span> <span class="operator">=</span> <span class="literal number integer">10</span><span class="punctuation">;</span>

<span class="keyword type">void</span><span class="operator">*</span> <span class="name function">my_malloc</span><span class="punctuation">(</span><span class="keyword type">void</span> <span class="operator">*</span><span class="name">ctx</span><span class="punctuation">,</span> <span class="keyword type">size_t</span> <span class="name">size</span><span class="punctuation">)</span>
<span class="punctuation">{</span>
    <span class="keyword type">int</span> <span class="name">padding</span> <span class="operator">=</span> <span class="operator">*</span><span class="punctuation">(</span><span class="keyword type">int</span> <span class="operator">*</span><span class="punctuation">)</span><span class="name">ctx</span><span class="punctuation">;</span>
    <span class="keyword">return</span> <span class="name">malloc</span><span class="punctuation">(</span><span class="name">size</span> <span class="operator">+</span> <span class="name">padding</span><span class="punctuation">);</span>
<span class="punctuation">}</span>
</pre></div>

With CSS

In a browser, when adding the CSS:

image

@ofek
Copy link
Sponsor

ofek commented Oct 1, 2020

Can this be merged?

@ofek
Copy link
Sponsor

ofek commented Nov 16, 2020

Needs a rebase

@ofek
Copy link
Sponsor

ofek commented Dec 9, 2020

Are there any remaining concerns or can we merge?

@di
Copy link
Sponsor Member

di commented Dec 10, 2020

I think this still needs work, baking in PURE_PYTHON_PEPS = [483, 484, 526] and everything around that doesn't really feel maintainable. Ideally we do what @hugovk says here:

I think it'd be good to default to Python for all :: blocks, and we can specify the language in the actual PEPs for non-Python :: blocks.

And then do the work of updating PEPs that are mis-highlighted.

@hugovk
Copy link
Member Author

hugovk commented Dec 11, 2020

Thanks for the bump! I'd forgotten I had something still do to.

Now updated to use Python highlighting for the default :: blocks, and things like highlight:: c can be used for other languages.

@@ -39,3 +39,5 @@ django-filter==1.1.0
django-ordered-model==3.4.1
django-widget-tweaks==1.4.8
django-countries==6.1.3

pygments==2.7.3 # This will be not needed when PEPs are moved to RtD.
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I understand this comment. Is there a plan to host the PEPs elsewhere?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the plan is to build PEPs using Sphinx and host them on Read the Docs at peps.python.org: python/peps#2 (June 2016).

There's a PR to do add Sphinx support, but it's a big one and hasn't been reviewed yet: python/peps#1385 (April 2020).

Hence reviving this PR.

Comment on lines 22 to 27
# To simplify syntax highlighting, all literal blocks (those produced by ::)
# in the following PEPs will be automatically highlighted using Python lexer.
# PEP editors/authors could make simple PRs extending this list.
# This will be not needed when PEPs are moved to RtD and all code blocks are
# formatted using .. code:: language.
PURE_PYTHON_PEPS = [483, 484, 526]
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is no longer used.

Copy link
Sponsor Member

@di di left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I don't have the ability to merge PRs here)

@ofek
Copy link
Sponsor

ofek commented Jun 2, 2021

Who can merge?

@ofek
Copy link
Sponsor

ofek commented Nov 24, 2021

@JelleZijlstra since python/peps#1577 was just merged, can this now be too?

@JelleZijlstra
Copy link
Member

I don't have commit access here.

@ofek
Copy link
Sponsor

ofek commented Dec 7, 2021

@ewdurbin Hello again! Would you be able to merge this?

@hugovk
Copy link
Member Author

hugovk commented Mar 7, 2022

Good news: PEP 676 has been accepted!

That means we'll soon have PEPs with syntax highlighting, something like this:

image

And dark mode:

image

So let's close this :)

@hugovk hugovk closed this Mar 7, 2022
@hugovk hugovk deleted the ilevkivskyi-colour branch March 7, 2022 20:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants