Adding a (latex) directive

60 views
Skip to first unread message

Stefano David

unread,
Oct 25, 2019, 3:17:15 AM10/25/19
to sphinx-users
Hi all,

I am trying to add to sphinx a directive to sphinx, but unsuccessfully. I think I still haven't grabbed all the points necessary to fully implement it.
My use case is quite simple: to have an alternative version .. rubric:: (call it .. altrubric::), and be able to alternate them. The idea is that they have a different style in HTML, but the same in PDF. For the HTML part, there is no problem, because I can use .. container:: to create a DIV and give it a CSS style.

Containers, however, do not get converted in any latex command, so they become simple text, instead of a (non-numbered) sectioning item. I then tried to duplicate the definition of visit_rubric and depart_rubric in latex.py writer and change their name in visit_altrubric and depart_altrubric, with no luck. I didn't think that implementing such a simple directive would prove such a diffcult job.Can someone point me to some example? Most of the directives I found are written for the HTML writer only and do not help me that much.

Thank you in advance for any pointer,
Stefano

Komiya Takeshi

unread,
Oct 26, 2019, 1:16:25 AM10/26/19
to sphinx...@googlegroups.com
Hi,

I'd like to see your your source code. Could you share it for us?

BTW, rubric directive takes :class: option to give CSS class for the
node in HTML output. I think it might help your case.

Thanks,
Takeshi KOMIYA

2019年10月25日(金) 16:17 Stefano David <ste...@gmail.com>:
> --
> You received this message because you are subscribed to the Google Groups "sphinx-users" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to sphinx-users...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/sphinx-users/3651d816-ed6f-4f7e-8bca-ba074357fbe2%40googlegroups.com.

Stefano David

unread,
Nov 14, 2019, 1:22:35 PM11/14/19
to sphinx-users
Hi Takeshi,


On Saturday, 26 October 2019 07:16:25 UTC+2, Komiya Takeshi wrote:
Hi,

I'd like to see your your source code. Could you share it for us?
First of all, I am very sorry for the late reply, I have been quite busy.

The good news is, however, that I made some more tests and I was able to have the ".. altrubric:: test" produce a \subsection*{test} in the latex output, as I wanted.
Unfortunately, in the HTML the .. altrubric:: directive produces only a <p class="rubric">test</p>, which is unexpected and I have no idea how I could fix.

The code is the following, adapted from a few examples found in this group and elsewhere:

*****
class altrubric(nodes.rubric):
    pass

def visit_altrubric(self, node):
    # type: (nodes.Element) -> None
    if len(node) == 1 and node.astext() in ('Footnotes', _('Footnotes')):
        raise nodes.SkipNode
    self.body.append('\\subsubsection*{')
    self.context.append('}\n')
    self.in_title = 1
   
def depart_altrubric(self, node):
    # type: (nodes.Element) -> None
    self.in_title = 0
    self.body.append(self.context.pop())

   
def visit_altrubric_html(self, node):
    self.body.append(self.starttag(node, 'rubric', '',
                                      CLASS='rubric altrubric'))

def depart_altrubric_html(self, node):
    pass

class AltRubricDirective(SphinxDirective): 
    has_content = False
    required_arguments = 1

    def run(self):
        set_classes(self.options)
        altrubric_text = self.arguments[0]
        textnodes, messages = self.state.inline_text(altrubric_text, self.lineno)
        altrubric = nodes.rubric(altrubric_text, '', *textnodes, **self.options)
        self.add_name(altrubric)
        return [altrubric] + messages

def setup(app):
    app.add_node(altrubric,
                 html=(visit_altrubric_html, depart_altrubric_html),
                 epub=(visit_altrubric, depart_altrubric),
                 latex=(visit_altrubric, depart_altrubric))
*****
I also tried to move visit_altrubric_html, depart_altrubric_html to the html.py writer class, without any change in the output. Same result even using other examples from the html builder, like e.g. atts['class'] += 'altrubric'. I also tried to add the class directly in the class altrubric(nodes.rubric), again with no results.

BTW, rubric directive takes :class: option to give CSS class for the
node in HTML output. I think it might help your case.
No, it does not seem to help in this case, because the container creates a <div> <p>...</p></div>, while the rubric a single <p class="rubric altrubric">..</p> which for some reasons receives only the rubric's CSS and the .altrubric>:before CSS rule does not work anymore. (but this is a problem which is OT here and I can not investigate right now, because it would require quite a number of changes).

Thank you and best regards,
Stefano

Komiya Takeshi

unread,
Nov 16, 2019, 6:14:34 AM11/16/19
to sphinx...@googlegroups.com
Hi,

It seems your code does not use `altrubric` node in AltRubricDirective.
Let's look into AltRubric.run():

> def run(self):
> set_classes(self.options)
> altrubric_text = self.arguments[0]
> textnodes, messages = self.state.inline_text(altrubric_text, self.lineno)
> altrubric = nodes.rubric(altrubric_text, '', *textnodes, **self.options)
> self.add_name(altrubric)
> return [altrubric] + messages

It generates a node via `nodes.rubric()`. It should be replaced by
`altrubric` class instead.

On my local, it works fine with above change and `app.add_directive()`
call in setup() function.

Thanks,
Takeshi KOMIYA

2019年11月15日(金) 3:22 Stefano David <ste...@gmail.com>:
> --
> You received this message because you are subscribed to the Google Groups "sphinx-users" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to sphinx-users...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/sphinx-users/39b36f73-1de5-4ba1-b391-ebd615140f21%40googlegroups.com.

Stefano David

unread,
Nov 16, 2019, 8:39:53 AM11/16/19
to sphinx-users
Hi Takeshi,

Thanks for your prompt reply,

On Saturday, 16 November 2019 12:14:34 UTC+1, Komiya Takeshi wrote:
 
>        altrubric = nodes.rubric(altrubric_text, '', *textnodes, **self.options)

It generates a node via `nodes.rubric()`. It should be replaced by
`altrubric` class instead.
You're right, but when I try to use altrubric in that line, Exceptions are always thrown. My poor python knowkedge does not help either...


On my local, it works fine with above change and `app.add_directive()`
call in setup() function.
Yes, I have the app.add_directive call, I just did not copy&paste it. My bad.

Thank you for your patience!
Stefano

Komiya Takeshi

unread,
Nov 16, 2019, 10:15:03 AM11/16/19
to sphinx...@googlegroups.com
HI Stefano,

Please share the exception you got. I would be able to help you.

Thanks,
Takeshi KOMIYA

2019年11月16日(土) 22:39 Stefano David <ste...@gmail.com>:
> --
> You received this message because you are subscribed to the Google Groups "sphinx-users" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to sphinx-users...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/sphinx-users/7d98dbd5-90b4-44c4-befc-431cbba77c9d%40googlegroups.com.

Stefano David

unread,
Nov 17, 2019, 4:07:17 AM11/17/19
to sphinx-users
Hi Takeshi,


On Saturday, 16 November 2019 16:15:03 UTC+1, Komiya Takeshi wrote:
HI Stefano,

Please share the exception you got. I would be able to help you.
My first try was the following:

Exception occurred:
  File "/home/stefano/sphinx-sandbox/source/conf.py", line 230, in run
    altrubric = altrubric.rubric(altrubric_text, '', *textnodes, **self.options)
UnboundLocalError: local variable 'altrubric' referenced before assignment

If I replace the abolve line with code with

arb = altrubric(altrubric_text, '', *textnodes, **self.options)

I get

Exception occurred:
  File "/usr/local/lib/python3.7/dist-packages/sphinx/builders/__init__.py", line 506, in write_doctree
    pickle.dump(doctree, f, pickle.HIGHEST_PROTOCOL)
_pickle.PicklingError: Can't pickle <class 'altrubric'>: attribute lookup altrubric on builtins failed

I also tried this one, although I knew it would fail:

Exception occurred:
  File "/home/stefano/000-work/sphinx-sandbox/source/conf.py", line 230, in run
    arb = nodes.altrubric(altrubric_text, '', *textnodes, **self.options)
AttributeError: module 'docutils.nodes' has no attribute 'altrubric'

So, I am quite stuck...
Thank you in advance!
Stefano

Komiya Takeshi

unread,
Nov 17, 2019, 7:09:52 AM11/17/19
to sphinx...@googlegroups.com
Where do you writing code? If you're using `conf.py`, please move them
to independent file. `conf.py` is not good to implement extensions.

refs: related issue
https://github.com/sphinx-doc/sphinx/issues/6751

2019年11月17日(日) 18:07 Stefano David <ste...@gmail.com>:
> --
> You received this message because you are subscribed to the Google Groups "sphinx-users" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to sphinx-users...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/sphinx-users/053ea3b3-aed9-4cf4-a207-4f968f1178b8%40googlegroups.com.

Witthaya Phaliam

unread,
Nov 17, 2019, 8:04:47 AM11/17/19
to sphinx...@googlegroups.com


ดาวน์โหลด Outlook for Android

From: sphinx...@googlegroups.com <sphinx...@googlegroups.com> on behalf of Komiya Takeshi <i.tk...@gmail.com>
Sent: Sunday, November 17, 2019 7:09:37 PM
To: sphinx...@googlegroups.com <sphinx...@googlegroups.com>
Subject: Re: [sphinx-users] Adding a (latex) directive
 

Stefano David

unread,
Nov 25, 2019, 10:12:35 AM11/25/19
to sphinx-users
Hi Takeshi,


On Sunday, 17 November 2019 13:09:52 UTC+1, Komiya Takeshi wrote:
Where do you writing code? If you're using `conf.py`, please move them
to independent file. `conf.py` is not good to implement extensions.

Thanks, that made the job. I was not aware that extension should better be written in indipendent files, I thought that it were simpler to have everything in conf.py for testing purposes.

Let me also add that I had to slightly modify the AltRubricDirective class as follows:

class AltRubricDirective(SphinxDirective):
    #has_content = False
    required_arguments = 1
    optional_arguments = 0
    final_argument_whitespace = True


    def run(self):
        set_classes(self.options)
        altrubric_text = self.arguments[0]
        textnodes, messages = self.state.inline_text(altrubric_text, self.lineno)
        arb = altrubric(altrubric_text, '', *textnodes, **self.options)
        return [arb] + messages

Now it works as expected, so let me thank you once more for your kind and invaluable assistance!

Bests regards,
Stefano
Reply all
Reply to author
Forward
0 new messages