From 1f17afaa7c46b923c8b34adb4ca5592b35779952 Mon Sep 17 00:00:00 2001
From: Robin Sonnabend <robin@fsmpi.rwth-aachen.de>
Date: Sat, 25 Feb 2017 17:15:09 +0100
Subject: [PATCH] Render todos in tex protocol

---
 models/database.py     |  12 +++++
 parser.py              | 117 ++++++++++++++++++++++++++++++-----------
 tasks.py               |   9 ++--
 templates/protocol.tex |  14 +----
 4 files changed, 106 insertions(+), 46 deletions(-)

diff --git a/models/database.py b/models/database.py
index 215c3da..75fbf0f 100644
--- a/models/database.py
+++ b/models/database.py
@@ -312,6 +312,18 @@ class Todo(db.Model):
         ]
         return " ".join(parts)
 
+    def render_latex(self, current_protocol=None):
+        is_new = len(self.protocols) == 1
+        if current_protocol is not None:
+            is_new = self.get_first_protocol() == current_protocol
+        return r"\textbf{{{}}}: {}: {} -- {}".format(
+            "Neuer Todo" if is_new else "Todo",
+            self.who,
+            self.description,
+            self.get_state_tex()
+        )
+
+
 
 class TodoProtocolAssociation(db.Model):
     __tablename__ = "todoprotocolassociations"
diff --git a/parser.py b/parser.py
index ab64dd8..80b35f0 100644
--- a/parser.py
+++ b/parser.py
@@ -1,6 +1,7 @@
 import regex as re
 import sys
 from collections import OrderedDict
+from enum import Enum
 
 from shared import escape_tex
 
@@ -24,12 +25,20 @@ class ParserException(Exception):
             result += "\n" + self.explanation
         return result
 
+class RenderType(Enum):
+    latex = 0
+    wikitext = 1
+    plaintext = 2
+
+def _not_implemented(self, render_type):
+    return NotImplementedError("The rendertype {} has not been implemented for {}.".format(render_type.name, self.__class__.__name__))
+
 class Element:
     """
     Generic (abstract) base element. Should never really exist.
     Template for what an element class should contain.
     """
-    def render(self, show_private):
+    def render(self, render_type, show_private, level=None, protocol=None):
         """
         Renders the element to TeX.
         Returns:
@@ -94,8 +103,8 @@ class Content(Element):
         self.children = children
         self.linenumber = linenumber
 
-    def render(self, show_private):
-        return "".join(map(lambda e: e.render(show_private), self.children))
+    def render(self, render_type, show_private, level=None, protocol=None):
+        return "".join(map(lambda e: e.render(render_type, show_private, level=level, protocol=protocol), self.children))
 
     def dump(self, level=None):
         if level is None:
@@ -146,8 +155,15 @@ class Text:
         self.text = text
         self.linenumber = linenumber
 
-    def render(self, show_private):
-        return escape_tex(self.text)
+    def render(self, render_type, show_private, level=None, protocol=None):
+        if render_type == RenderType.latex:
+            return escape_tex(self.text)
+        elif render_type == RenderType.wikitext:
+            return self.text
+        elif render_Type == RenderType.plaintext:
+            return self.text
+        else:
+            raise _not_implemented(self, render_type)
 
     def dump(self, level=None):
         if level is None:
@@ -172,11 +188,15 @@ class Tag:
         self.values = values
         self.linenumber = linenumber
 
-    def render(self, show_private):
-        if self.name == "url":
-            return r"\url{{{}}}".format(self.values[0])
-        #return r"\textbf{{{}:}} {}".format(escape_tex(self.name.capitalize()), "; ".join(map(escape_tex, self.values)));
-        return r"\textbf{{{}:}} {}".format(escape_tex(self.name.capitalize()), escape_tex(self.values[0]))
+    def render(self, render_type, show_private, level=None, protocol=None):
+        if render_type == RenderType.latex:
+            if self.name == "url":
+                return r"\url{{{}}}".format(self.values[0])
+            elif self.name == "todo":
+                return self.todo.render_latex(current_protocol=protocol)
+            return r"\textbf{{{}:}} {}".format(escape_tex(self.name.capitalize()), escape_tex(self.values[0]))
+        else:
+            raise _not_implemented(self, render_type)
 
     def dump(self, level=None):
         if level is None:
@@ -199,7 +219,7 @@ class Empty(Element):
     def __init__(self, linenumber):
         linenumber = linenumber
 
-    def render(self, show_private):
+    def render(self, render_type, show_private, level=None, protocol=None):
         return ""
 
     def dump(self, level=None):
@@ -220,8 +240,13 @@ class Remark(Element):
         self.value = value
         self.linenumber = linenumber
 
-    def render(self, show_private):
-        return r"\textbf{{{}}}: {}".format(self.name, self.value)
+    def render(self, render_type, show_private, level=None, protocol=None):
+        if render_type == RenderType.latex:
+            return r"\textbf{{{}}}: {}".format(self.name, self.value)
+        elif render_type == RenderType.wikitext:
+            return "{}: {}".format(self.name, self.value)
+        elif render_type == RenderType.plaintext:
+            return "{}: {}".format(RenderType.plaintex)
 
     def dump(self, level=None):
         if level is None:
@@ -266,28 +291,58 @@ class Fork(Element):
         stripped_name = name.replace(":", "").strip()
         return stripped_name in config.PRIVATE_KEYS
 
-    def render(self, show_private, toplevel=False):
+    def render(self, render_type, show_private, level, protocol=None):
         name_line = self.name if self.name is not None and len(self.name) > 0 else ""
-        begin_line = r"\begin{itemize}"
-        end_line = r"\end{itemize}"
-        content_parts = []
-        for child in self.children:
-            part = child.render(show_private)
-            if len(part.strip()) == 0:
-                continue
-            if not part.startswith(r"\item"):
-                part = r"\item {}".format(part)
-            content_parts.append(part)
-        content_lines = "\n".join(content_parts)
-        if toplevel:
-            return "\n".join([begin_line, content_lines, end_line])
-        elif self.test_private(self.name):
-            if show_private:
-                return content_lines
+        if render_type == RenderType.latex:
+            begin_line = r"\begin{itemize}"
+            end_line = r"\end{itemize}"
+            content_parts = []
+            for child in self.children:
+                part = child.render(render_type, show_private, level=level+1, protocol=protocol)
+                if len(part.strip()) == 0:
+                    continue
+                if not part.startswith(r"\item"):
+                    part = r"\item {}".format(part)
+                content_parts.append(part)
+            content_lines = "\n".join(content_parts)
+            if level == 0:
+                return "\n".join([begin_line, content_lines, end_line])
+            elif self.test_private(self.name):
+                if show_private:
+                    return content_lines
+                else:
+                    return ""
             else:
+                return "\n".join([name_line, begin_line, content_lines, end_line])
+        elif render_type == RenderType.wikitext:
+            title_line = "{0}{1}{0}".format("=" * (level + 2), name_line)
+            content_parts = []
+            for child in self.children:
+                part = child.render(render_type, show_private, level=level+1, protocol=protocol)
+                if len(part.strip()) == 0:
+                    continue
+                content_parts.append(part)
+            content_lines = "{}\n{}".format(title_line, "\n".join(content_parts))
+            if self.test_private(self.name) and not show_private:
                 return ""
+            else:
+                return content_lines
+        elif render_type == RenderType.plaintext:
+            title_line = "{} {}".format("#" * (level + 1), name_line)
+            content_parts = []
+            for child in self.children:
+                part = child.render(render_Type, show_private, level=level+1, protocol=protocol)
+                if len(part.strip()) == 0:
+                    continue
+                content_parts.append(part)
+            content_lines = "{}\n{}".format(title_line, "\n".join(content_parts))
+            if self.test_private(self.name) and not show_private:
+                return ""
+            else:
+                return content_lines
         else:
-            return "\n".join([name_line, begin_line, content_lines, end_line])
+            raise _not_implemented(self, render_type)
+
 
     def get_tags(self, tags=None):
         if tags is None:
diff --git a/tasks.py b/tasks.py
index 972edea..8aee9d2 100644
--- a/tasks.py
+++ b/tasks.py
@@ -10,7 +10,7 @@ from models.errors import DateNotMatchingException
 from server import celery, app
 from shared import db, escape_tex, unhyphen, date_filter, datetime_filter, date_filter_long, date_filter_short, time_filter, class_filter
 from utils import mail_manager, url_manager, encode_kwargs, decode_kwargs
-from parser import parse, ParserException, Element, Content, Text, Tag, Remark, Fork
+from parser import parse, ParserException, Element, Content, Text, Tag, Remark, Fork, RenderType
 
 import config
 
@@ -164,6 +164,7 @@ def parse_protocol_async(protocol_id, encoded_kwargs):
                     elif other_field not in todo_tags_internal:
                         todo_tags_internal.append(other_field)
                 todo.tags = ";".join(todo_tags_internal)
+                todo_tag.todo = todo
                 db.session.commit()
             old_decisions = list(protocol.decisions)
             for decision in old_decisions:
@@ -189,8 +190,10 @@ def parse_protocol_async(protocol_id, encoded_kwargs):
                 db.session.add(top)
             db.session.commit()
 
-            latex_source_private = texenv.get_template("protocol.tex").render(protocol=protocol, tree=tree, show_private=True)
-            latex_source_public = texenv.get_template("protocol.tex").render(protocol=protocol, tree=tree, show_private=False)
+            private_states = [False]
+
+            latex_source_private = texenv.get_template("protocol.tex").render(protocol=protocol, tree=tree, show_private=True, render_type=RenderType.latex)
+            latex_source_public = texenv.get_template("protocol.tex").render(protocol=protocol, tree=tree, show_private=False, render_type=RenderType.latex)
             compile(latex_source_public, protocol, show_private=False)
             if latex_source_private != latex_source_public:
                 compile(latex_source_private, protocol, show_private=True)
diff --git a/templates/protocol.tex b/templates/protocol.tex
index be04475..5acd7c3 100644
--- a/templates/protocol.tex
+++ b/templates/protocol.tex
@@ -45,18 +45,8 @@ Beginn der Sitzung: \VAR{protocol.start_time|timify}
 
 \ENV{for top in tree.children}
     \ENV{if top|class == "Fork"}
-        \TOP{\VAR{top.name|escape_tex}} % here we probably have information doubly
-        \ENV{if top.name == "Todos"}
-            \ENV{if protocol.todos|length > 0}
-                \begin{itemize}
-                    \ENV{for todo in protocol.todos}
-                        \item \VAR{todo.who}: \VAR{todo.description} -- \VAR{todo.get_state_tex()}
-                    \ENV{endfor}
-                \end{itemize}
-            \ENV{endif}
-        \ENV{else}
-            \VAR{top.render(toplevel=True, show_private=show_private)}
-        \ENV{endif}
+        \TOP{\VAR{top.name|escape_tex}}
+        \VAR{top.render(render_type=render_type, level=0, show_private=show_private, protocol=protocol)}
     \ENV{endif}
 \ENV{endfor}
 
-- 
GitLab