Creating a Sphinx extension to switch between snake_case and PascalCase syntax dynamically

14 views
Skip to first unread message

Hugo Locurcio

unread,
Oct 13, 2020, 10:30:52 AM10/13/20
to sphinx-users

Hello,

I'm one of the main contributors to Godot's documentation. I'm looking at developing a Sphinx extension to make a documentation page switchable between snake_case and PascalCase syntax for method references (which are links) and *inline* code. (We've already got multiline code samples covered by the sphinx-tabs extension.)
See this issue on the godot-docs repository: https://github.com/godotengine/godot-docs/issues/828

For example, I have a page like this: https://docs.godotengine.org/en/stable/classes/class_node.html

I want to add a button on the page that switches between snake_case (GDScript) and PascalCase (C#) syntax for all methods/properties on the page. I've looked at writing a  Sphinx extension, but I don't know if you can expose new "inline blocks" like :ref: or :kbd: which are built-in.
For inline code samples, we currently do this:

    To enable processing, call the ``set_process(true)`` method.

I'd imagine we would have to create a custom syntax like this (GDScript on the left, C# on the right):

    To enable processing, call the :code:`set_process(true);;SetProcess(true)` method.

(The double semicolon separator is just an example, but we need to use something we'll never use for other purposes in inline code samples.)

As for method references, we currently use this:

    :ref:`_physics_process<class_Node_method__physics_process>`

For this case, I think it would be enough to use a custom inline block that behaves like :ref:, but tells the JavaScript side that the syntax should be switched depending on the user preference:

     :coderef:`_physics_process<class_Node_method__physics_process>`

I don't think we can run the syntax-switching logic on every link in the page, as there would be many false positives. The same goes for inline code, since parts of the Godot API are always snake_case, even when using C#.

As for the syntax switching itself, it will be done using JavaScript code (which I can write myself). Therefore, my question is only about being able to clearly identify the text whose syntax must be changed.

Thanks in advance for answering :)
Hugo Locurcio

Hugo Locurcio

unread,
Oct 28, 2020, 11:22:48 AM10/28/20
to sphinx-users
I've done some progress on my implementation. There are good news and bad news :)

I've managed to implement a snake_case/PascalCase conversion role for literal blocks (``like_this`` is replaced by :snakepascal:`like_this;;LikeThis`). The associated JavaScript and CSS code I've developed works great too.
However, I haven't managed to replicate the same role for "reference" links. Here's the code snippet that defines the :snakepascal-ref: role I'm trying to create:

def snakepascal_reference_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
    if "<" in text:
        # Manually named reference
        refid = text.split("<")[1].split(">")[0]
    else:
        # Automatically named reference
        refid = text

    node = nodes.reference(rawtext, text, refid=refid, classes=["snakepascal"], **options)
    return [node], []

Usage:

     Manually named reference: :snakepascal-ref:`custom_multiplayer<class_Node_property_custom_multiplayer>`

     Automatically named reference: :snakepascal-ref:`class_Node_property_custom_multiplayer`

I thought setting the `refid` parameter would make Sphinx find the reference automatically like it does with the :ref: role, but it seems to just create a literal hash-link. I want to use the same reference acquisition logic as Sphinx itself so I don't have to type out internal documentation URLs fully.

(At the end of the day, I just want to associate a custom CSS class to the reference link so it can be used from JavaScript.)

Reply all
Reply to author
Forward
0 new messages