jgm / pandoc

Universal markup converter
https://pandoc.org
Other
34.83k stars 3.39k forks source link

LaTex/Beamer add hook before \begin{frame}... and after \end{frame} #4403

Open NMarkgraf opened 6 years ago

NMarkgraf commented 6 years ago

I think it would be a great idea to add the possibility to call a hook macro in latex/beamer right before and after the creation of a frame.

This would make it possible to translate something like

## Exercise: a new quiz {hook=exercisemode}

Just an  example ...

## No exercise 

Nothing else

to an latex output with might change the behavior frame title styling etc:

\exercisemodetrue
\begin{frame}
\frametitle{%
\protect\hypertarget{exercise-a-new-quiz}{%
 Exercise: a new quiz }}

Just an example ...
\end{frame}
\exercisemodefalse

\begin{frame}
\frametitle{%
\protect\hypertarget{o-exercise}{%
 No exercise  }}

Nothing else ...
\end{frame}

I need something like this desperately to change the frame title style of a slide when it shows exercises..

Thanks Norman

cagix commented 6 years ago

Do you really need to enclose the complete frame in the exercise mode, i.e. do you need \exercisemodetrue to appear before \begin{frame} and \exercisemodefalse to appear after \end{frame}?

If it would suffice to wrap just the content of your frame into the exercise mode, you could use a simple lua-filter like

local exercise = false

function Header(h)
    local exercisemode = pandoc.Null()

    -- handle end of previous excercise mode
    if exercise then
        exercise = false
        exercisemode = pandoc.RawBlock("latex", "\\exercisemodefalse")
    end

    -- handle current header: start exercise if attribut `hook` is set to `exercisemode`
    if h.attributes["hook"] == "exercisemode" then
        exercise = true
        return { exercisemode, h, pandoc.RawBlock("latex", "\\exercisemodetrue") }
    end

    -- else return header
    return { exercisemode, h }
end

This filter would produce the following TeX from your example (using --slide-level=2):

\begin{frame}{%
\protect\hypertarget{exercise-a-new-quiz}{%
Exercise: a new quiz}}

\exercisemodetrue

Just an example \ldots{}

\exercisemodefalse

\end{frame}

\begin{frame}{%
\protect\hypertarget{no-exercise}{%
No exercise}}

Nothing else

\end{frame}
mb21 commented 6 years ago

If it would suffice to wrap just the content of your frame into the exercise mode

then you could also you write the raw TeX (i.e. \exercisemodetrue) as part of the markdown

NMarkgraf commented 6 years ago

If you write raw TeX like @mb21 suggested, this raw TeX would be part of the frame before. Because every Header of a certain level is acting greedy until the next Header of the same or higher level. So the raw TeX-Block in the AST would be part of the last Header, which means that it will be written inside of the frame before the current frame. And that is not a solution, because you need it between \end{frame} and \begin{frame}.

So that is not the right way to fix the problem.

(Yes, I do think this is a design problem of the current AST-design! ;-) )

That is also true for (any) filter suggestion, because setting anything inside of a frame won't change the current frame (and also not the next frame!) or anything inside of the frame title environment. If you write \begin{frame} everything inside will be like in a sandbox and don't harm the frame code.

So, change the behavior inside of the pandoc latex-writer is, for me, the only possible solution. -- Sorry.

Thanks to @mb21 and @cagix, but it your ideas won't work .. :-(

jgm commented 6 years ago

Currently we reorganize the AST for slides in the writer, so the filter can't get to the slide structure.

Now that we have native Divs, we could consider reorganizing things:

It's a bit complex but worth considering.

NMarkgraf commented 6 years ago

I'm not sure about if this would make it easier. Complex, may be to complicated, if you would ask me. If I understand it correctly

something like

# section
## slide
Lore ipsum ...

## slide
Lore ipsum ...

will first be converted to something like

[Div class="section" content="section",
  [Div class="slide" content="Lore Ipsum ..."],
  [Div class="slide" content="Lore ipsum ..."]
]

so that it will be possible to add something in between like

[Div class="section" content="section",
  [RawBlock ...],
  [Div class="slide" content="Lore Ipsum ..."],
  [Div class="slide" content="Lore ipsum ..."],
  [RawBlock ...]
]

or do I misunderstood something?

jgm commented 6 years ago

Yes, you understand the idea.

NMarkgraf commented 6 years ago

Okay, that would be perfect. - When it will arrive in the releases? ;-) --- Yes, i'm pushing, 'cause I need it badly! :-)

NMarkgraf commented 6 years ago

Sorry,

is there anything I could test or use in this direction? -- Maybe in a branch? ;-)

Yours Norman

jgm commented 6 years ago

Sorry...I have limited time to work on pandoc; you shouldn't expect any changes soon.