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

Different Item replacement for Environments #30

Open
TimoBergerbusch opened this issue Jan 17, 2020 · 1 comment
Open

Different Item replacement for Environments #30

TimoBergerbusch opened this issue Jan 17, 2020 · 1 comment

Comments

@TimoBergerbusch
Copy link

TimoBergerbusch commented Jan 17, 2020

Hello everyone.

First of all: nice work!
The lib really helps me a lot.

But I'm currently facing the issue that for the generated latex code:

\begin{enumerate}% 
	\item% 
		\begin{itemize}%
			\item% 
				BLA BLA 1.1 
			\item% 
				BLA BLA 1.2 
		\end{itemize}% 
	\item
		\begin{itemize}% 
			\item% 
				Word = BLA BLA 2.1 
			\item% 
				Word = BLA BLA 2.2 
		\end{itemize}% 
	\item%
		BLABLA 3 
\end{enumerate}

I'm not able to distinguish the "item" for enumerations and for itemize.

What I desire is something like:

1. 
   - BLA BLA 1.1
   - BLA BLA 1.2
2.
   - BLA BLA 2.1
   - BLA BLA 2.2
3.
   BLA BLA 3

I tried to fiddle with the default_context_db, or to post-process and replace the generated " * \n" strings, but I believe in a well-structured framework like this, there would be a better solution.

Thanks in advance!

@phfaist
Copy link
Owner

phfaist commented Jan 25, 2020

Hi, great question. This is slightly tricky because the default latex2text replacement texts aren't context-aware. I mean, the replacement text for "\item" is generated by default without knowing whether the macro is in an {enumerate} or {itemize} environment nor how many other "\item"'s were present before. You can track the context explicitly however, and here's a simple solution:

from pylatexenc import macrospec, latexwalker, latex2text

class EnumContext:
    def __init__(self, env=None, nest_level=0, item_no=0):
        self.env = env
        self.nest_level = nest_level
        self.item_no = item_no

def enum_environment_to_text(n, l2tobj):
    if n.environmentname not in ("enumerate", "itemize"):
        raise RuntimeError("environment was expected to be enumerate or itemize")
    try:
        old_context = getattr(l2tobj, 'context_enum_environment', EnumContext())
        l2tobj.context_enum_environment = EnumContext(n.environmentname, old_context.nest_level+1, 0)
        s = l2tobj.nodelist_to_text(n.nodelist)
    finally:
        l2tobj.context_enum_environment = old_context
    return s

def item_to_text(n, l2tobj):
    enumcontext = getattr(l2tobj, 'context_enum_environment', EnumContext())
    if n.nodeoptarg:
        itemstr = l2tobj.nodelist_to_text([n.nodeoptarg])
    if enumcontext.env == 'itemize':
        itemstr = '- '
    elif enumcontext.env == 'enumerate':
        enumcontext.item_no += 1
        itemstr = str(enumcontext.item_no) + '. '
    else:
        itemstr = '* ' # \item not in \begin{enumerate} or \begin{itemize} environment
    return '\n' + '  '*enumcontext.nest_level + itemstr


c = latex2text.get_default_latex_context_db()
c.add_context_category(
    'enum-context',
    macros=[
        latex2text.MacroTextSpec('item', simplify_repl=item_to_text)
    ],
    environments=[
        latex2text.EnvironmentTextSpec('enumerate', simplify_repl=enum_environment_to_text),
        latex2text.EnvironmentTextSpec('itemize', simplify_repl=enum_environment_to_text),
    ],
    prepend=True
)

l2t = latex2text.LatexNodes2Text(latex_context=c)

print(l2t.latex_to_text(r"""
Hello world.
\begin{enumerate}
\item first item
\item second item
\item group of itemized items
    \begin{itemize}
    \item subitem
    \item another subitem
    \end{itemize}
\item last item
\end{enumerate}
"""))

The result is:

Hello world.

  1.  first item

  2.  second item

  3.  group of itemized items

    -  subitem

    -  another subitem

  4.  last item

The idea is that we set an attribute context_enum_environment to the LatexNodes2Text object to track enumerate/itemize environments (including nesting level) and count how many \item macros are encountered at each level. This is all done in the replacement callbacks for the \item macro and for the \begin{enumerate} and \begin{itemize} environments.

Hope this helps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants