Misc fixes:
[sixth.git] / src / main / java / eu / svjatoslav / sixth / core / document / Heading.java
1 package eu.svjatoslav.sixth.core.document;
2
3 import eu.svjatoslav.commons.string.String2;
4 import eu.svjatoslav.commons.string.tokenizer.TokenizerMatch;
5 import eu.svjatoslav.sixth.core.document.content.ListElement;
6 import eu.svjatoslav.sixth.core.document.text.FormattedText;
7
8 import java.util.ArrayList;
9 import java.util.List;
10
11 import static eu.svjatoslav.sixth.core.document.Helper.TG_LIST;
12
13 public class Heading {
14     public final FormattedText name;
15     public final int level;
16     public final Heading parent;
17     private final List<Heading> children = new ArrayList<>();
18
19     public final ListElement rootListElement = new ListElement(null, -2, null, "");
20     private ListElement currentListElement = rootListElement;
21
22     public Heading(FormattedText name, int level, Heading parent){
23         this.level = level;
24         this.name = name;
25         this.parent = parent;
26     }
27
28     public void addChild(Heading heading){
29         children.add(heading);
30     }
31
32     public List<Heading> getChildren(){
33         return children;
34     }
35
36     public String toMD () {
37         StringBuilder sb = new StringBuilder();
38
39         if (level > 0) sb.append(enlistTitleInMD());
40
41         rootListElement.toMD(sb, -2);
42
43         children.stream().map(Heading::toMD).forEach(sb::append);
44
45         return sb.toString();
46     }
47
48     private String enlistTitleInMD() {
49         String2 s = new String2();
50         s.append("#", level).append(" ").append(name.toMD(0)).append("\n");
51         return s.toString();
52     }
53
54     public ListElement getCurrentHeading(){
55         return currentListElement;
56     }
57
58     public void parse(TokenizerMatch tm){
59
60         int indent = Utils.getLineIndent(tm.token);
61         if (indent > -1 && indent <= currentListElement.indent) handleListDepthDecrease(indent);
62
63         if (tm.isGroup(TG_LIST)){
64             parseList(tm);
65             return;
66         }
67
68         currentListElement.parse(tm);
69     }
70
71     private void handleListDepthDecrease(int indent) {
72         while (true){
73             if (currentListElement.parent.indent <= indent){
74                 currentListElement = currentListElement.parent;
75                 return;
76             }
77             currentListElement = currentListElement.parent;
78         }
79     }
80
81     private void parseList(TokenizerMatch tm) {
82         String[] listSections = tm.getRegExpGroups();
83         int indent = listSections[0].length();
84         String type = listSections[1];
85
86         String title = getPartialTitle(listSections);
87
88         if (indent > currentListElement.indent){
89             // list dept increases
90             ListElement newElement = new ListElement(title, indent, currentListElement, type);
91             currentListElement.addContent(newElement);
92             currentListElement = newElement;
93             return;
94         }
95
96         if (indent > currentListElement.parent.indent){
97             // list depth is the same
98             ListElement newElement = new ListElement(title, indent, currentListElement.parent, type);
99             currentListElement.parent.addContent(newElement);
100             currentListElement = newElement;
101             return;
102         }
103
104         throw new RuntimeException("Impossible condition reached. Must be a bug!");
105     }
106
107     private String getPartialTitle(String[] listSections) {
108         return listSections.length > 2 ? listSections[2] : "";
109     }
110
111 }