Misc fixes:
authorSvjatoslav Agejenko <svjatoslav@svjatoslav.eu>
Fri, 2 Oct 2020 14:45:00 +0000 (17:45 +0300)
committerSvjatoslav Agejenko <svjatoslav@svjatoslav.eu>
Fri, 2 Oct 2020 14:45:41 +0000 (17:45 +0300)
Fixed last content element and list title continuation detections.
Properly handle list depth decrease.
Better parsing of multiline list title.

src/main/java/eu/svjatoslav/sixth/core/document/Heading.java
src/main/java/eu/svjatoslav/sixth/core/document/Utils.java
src/main/java/eu/svjatoslav/sixth/core/document/content/ListElement.java

index ca72321..8a80d9c 100644 (file)
@@ -1,7 +1,6 @@
 package eu.svjatoslav.sixth.core.document;
 
 import eu.svjatoslav.commons.string.String2;
-import eu.svjatoslav.commons.string.tokenizer.Tokenizer;
 import eu.svjatoslav.commons.string.tokenizer.TokenizerMatch;
 import eu.svjatoslav.sixth.core.document.content.ListElement;
 import eu.svjatoslav.sixth.core.document.text.FormattedText;
@@ -58,6 +57,9 @@ public class Heading {
 
     public void parse(TokenizerMatch tm){
 
+        int indent = Utils.getLineIndent(tm.token);
+        if (indent > -1 && indent <= currentListElement.indent) handleListDepthDecrease(indent);
+
         if (tm.isGroup(TG_LIST)){
             parseList(tm);
             return;
@@ -66,11 +68,22 @@ public class Heading {
         currentListElement.parse(tm);
     }
 
+    private void handleListDepthDecrease(int indent) {
+        while (true){
+            if (currentListElement.parent.indent <= indent){
+                currentListElement = currentListElement.parent;
+                return;
+            }
+            currentListElement = currentListElement.parent;
+        }
+    }
+
     private void parseList(TokenizerMatch tm) {
         String[] listSections = tm.getRegExpGroups();
         int indent = listSections[0].length();
         String type = listSections[1];
-        FormattedText title = FormattedText.fromOrg(parseFullListTitle(getPartialTitle(listSections), tm.getTokenizer(), indent));
+
+        String title = getPartialTitle(listSections);
 
         if (indent > currentListElement.indent){
             // list dept increases
@@ -88,47 +101,11 @@ public class Heading {
             return;
         }
 
-        // list dept decreases
-        while (true){
-            if (currentListElement.parent.indent <= indent){
-                ListElement newElement = new ListElement(title, indent, currentListElement.parent.parent, type);
-                currentListElement.parent.parent.addContent(newElement);
-                currentListElement = newElement;
-                return;
-            }
-            currentListElement = currentListElement.parent;
-        }
-
+        throw new RuntimeException("Impossible condition reached. Must be a bug!");
     }
 
     private String getPartialTitle(String[] listSections) {
         return listSections.length > 2 ? listSections[2] : "";
     }
 
-    private String parseFullListTitle(String partialTitle, Tokenizer tokenizer, int listIndent){
-        StringBuilder sb = new StringBuilder();
-        sb.append(partialTitle);
-
-        while (tokenizer.hasMoreContent()){
-            final TokenizerMatch tm = tokenizer.getNextToken();
-
-            if (isContentContinuation(tm, listIndent, Helper.TG_NORMAL_TEXT)){
-                String titleContinuation = tm.token.substring(listIndent).trim();
-                sb.append("\n").append(titleContinuation);
-                continue;
-            }
-
-            tokenizer.unreadToken();
-            break;
-        }
-
-        return sb.toString();
-    }
-
-    public static boolean isContentContinuation(TokenizerMatch tm, int requiredIndent, String requiredGroup) {
-        if (tm.token.length() <= requiredIndent) return false;
-
-        return tm.isGroup(requiredGroup) && tm.token.substring(0, requiredIndent +1).trim().length() == 0;
-    }
-
 }
index 00166ef..4883d1d 100644 (file)
@@ -4,6 +4,8 @@ import eu.svjatoslav.commons.string.String2;
 
 public class Utils {
 
+    public static final char[] whitespace = new char[]{'\n', '\r', ' ', '\t'};
+
     public static String addIndentExceptFirstLine(String input, int indent) {
         String[] lines = input.split("\\r?\\n");
 
@@ -21,7 +23,34 @@ public class Utils {
     }
 
     public static boolean isBlank(String s){
-        return s.trim().length() == 0;
+        for (char c : s.toCharArray())
+            if (!isWhitespaceChar(c)) return false;
+
+        return true;
+    }
+
+    /**
+     * @return line indent in characters or -1 if line is blank or empty
+     */
+    public static int getLineIndent(String line){
+        for (int i = 0; i < line.length(); i++) {
+            if (!isWhitespaceChar(line.charAt(i)))
+                return i;
+        }
+        return -1;
+    }
+
+    public static boolean isWhitespaceChar(char c){
+        for (char whitespaceChar : whitespace)
+            if (whitespaceChar == c) return true;
+
+        return false;
+    }
+
+    public static String removePrefix(String string, int charsToRemove){
+        String2 s = new String2(string);
+        s.trimPrefix(charsToRemove);
+        return s.toString();
     }
 
 }
index 0db636f..5cfc791 100644 (file)
@@ -9,17 +9,18 @@ import java.util.List;
 
 import static eu.svjatoslav.sixth.core.document.Helper.*;
 import static eu.svjatoslav.sixth.core.document.Utils.isBlank;
+import static eu.svjatoslav.sixth.core.document.Utils.removePrefix;
 
 public class ListElement implements Content {
-    public final FormattedText name;
+    StringBuilder nameInOrg = new StringBuilder();
     public final int indent;
     public final ListElement parent;
     private final String type;
     private final List<Content> content = new ArrayList<>();
 
-    public ListElement(FormattedText name, int indent, ListElement parent, String type) {
+    public ListElement(String nameInOrg, int indent, ListElement parent, String type) {
         this.indent = indent;
-        this.name = name;
+        this.nameInOrg.append(nameInOrg);
         this.type = type;
         this.parent = parent;
     }
@@ -33,7 +34,7 @@ public class ListElement implements Content {
         Content contentElement = findCurrentContentElement();
         if (contentElement == null) return false;
 
-        return contentElement.getClass().isInstance(aClass);
+        return aClass.isInstance(contentElement);
     }
 
     public void addContent(Content contentElement){
@@ -86,12 +87,16 @@ public class ListElement implements Content {
         TextBlock textBlock;
         if (isLastContentElement(TextBlock.class)) {
             textBlock = ((TextBlock) findCurrentContentElement());
+        } if (content.isEmpty()){
+            // list title continuation
+            nameInOrg.append("\n").append(removePrefix(tm.token, indent + 2));
+            return;
         } else {
             textBlock = new TextBlock();
             content.add(textBlock);
         }
 
-        textBlock.addContent(tm.token + "\n");
+        textBlock.addContent(tm.token);
     }
 
     private void parseDocumentProperty(TokenizerMatch tm) {
@@ -123,7 +128,7 @@ public class ListElement implements Content {
 
         if (this.indent >= 0) {
             String2 s = new String2();
-            s.append(" ", indent).append(type).append(" ").append(name.toMD(indent + 2)).append("\n");
+            s.append(" ", indent).append(type).append(" ").append(getName().toMD(indent + 2)).append("\n");
             sb.append(s.toString());
         }
 
@@ -132,18 +137,22 @@ public class ListElement implements Content {
         }
     }
 
+    private FormattedText getName(){
+        return FormattedText.fromOrg(nameInOrg.toString());
+    }
+
     private void disablePlantUmlExport() {
 
         for (int i = 0; i< (content.size()-2); i++){
             if (!(content.get(i) instanceof MultilineCode)) continue;
 
             MultilineCode code = (MultilineCode) content.get(i);
-            if (!"plantuml".equalsIgnoreCase(code.language)) continue;;
+            if (!"plantuml".equalsIgnoreCase(code.language)) continue;
 
             if (!(content.get(i+1) instanceof DocumentPropertyCollection)) continue;
             DocumentPropertyCollection property = (DocumentPropertyCollection) content.get(i+1);
 
-            if (!property.hasProperty("results")) continue;;
+            if (!property.hasProperty("results")) continue;
 
             if (!(content.get(i+2) instanceof TextBlock)) continue;
             TextBlock textBlock = (TextBlock) content.get(i+2);