-
Notifications
You must be signed in to change notification settings - Fork 262
/
Numbers.java
158 lines (145 loc) · 5.35 KB
/
Numbers.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// This program inserts section numbers into a .md document (replacing
// any that are there). It also puts in the section numbers in
// cross-reference links.
// A heading line consists of: one or more #, a dotted section number,
// the section title, and the reference {#sec-name}
// A section cross-reference is: [Section 0](#sec-name)
import java.nio.file.*;
import java.util.*;
import java.io.*;
import java.util.regex.*;
public class Numbers {
public static Pattern inc = Pattern.compile("\\{%\\s+include(_relative)?\\s+([\\w.\\d/_-]+)");
public static Pattern sec = Pattern.compile("^[ \\t0-9\\.]*([#]+)\\h+(\\D|((\\d+\\.)+))");
public static Pattern ref = Pattern.compile("\\{#([\\w-]+)\\}");
public static Pattern cite = Pattern.compile("\\(#([\\w-]+)\\)");
public static Pattern seccite = Pattern.compile("(\\[Section [\\d\\.]+\\])\\(#([\\w-]+)\\)");
public static Pattern id = Pattern.compile("id=\"([a-zA-Z-]*)\"");
public static Set<String> cites = new HashSet<>();
public static Map<String,String> labels = new HashMap<>();
public static int[] counts = new int[100];
public static int depth = 0;
public static boolean replace = false;
public static boolean verbose = false;
public static void main(String[] args) {
int i = 0;
if (i < args.length && args[i].equals("-v")) { verbose = true; i++; }
if (i < args.length && args[i].equals("-r")) { replace = true; i++; }
process(args[i], false);
if (replace) {
depth = 0; counts = new int[100];
process(args[i], true);
}
if (verbose) System.out.println("Number of cites: " + cites.size());
//for (String s: cites) System.out.println(" " + s);
if (verbose) System.out.println("Number of labels: " + labels.size());
for (String s: cites) {
if (!labels.containsKey(s)) System.out.println(" No label: " + s);
}
}
public static String num() {
String s = "";
for (int k=0; k < depth; k++) s = s + counts[k] + '.';
return s;
}
public static void process(String file, boolean replace) {
if (verbose) System.out.println("Opening " + file);
try (FileReader f = new FileReader(file);
BufferedReader r = new BufferedReader(f)) {
PrintWriter w = null;
if (replace) w = new PrintWriter(new BufferedWriter(new FileWriter(file + ".tmp")));
String line;
// For the first line, we read it manually.
line = "";
char c;
while((c = (char)r.read()) != '\0' && c != '\n' && c != '\r') {
line = line + (char)c;
}
// Get the newline character by reading the file itself
String newlineChar = c == '\n' ? "\n" : "\r\n";
boolean first = true;
while ((line = first ? line : r.readLine()) != null) {
// Get the newline character by reading the file itself
first = false;
String out = line;
Matcher mid = id.matcher(line);
if (mid.find()) {
String label = mid.group(1);
labels.put(label,"0");
}
Matcher m = inc.matcher(line);
if (m.find()) {
if (replace) w.print(line + newlineChar);
String rel = m.group(1);
String newfile = m.group(2);
if (newfile.endsWith(".md")) {
String fn = rel == null ? "../_includes/" + newfile : newfile ;
process(fn, replace);
}
continue;
}
m = sec.matcher(line);
if (m.find() && m.start() == 0) {
String hashes = m.group(1);
String digits = m.group(3);
int textpos = m.end(1);
if (digits != null) textpos = m.end(3);
int k = hashes.length();
while (depth > k) counts[--depth] = 0;
if (k > depth+1) System.out.println("Skipping a level");
if (k > depth) ++depth;
counts[depth-1]++;
String n = num();
if (digits != null && !n.equals(digits)) System.out.println("number mismatch " + digits + " vs. " + n);
m = ref.matcher(line);
if (m.find()) {
String refname = m.group(1);
if (verbose) System.out.println(" " + refname + " : " + n);
labels.put(refname,n);
}
out = (hashes + " " + n + line.substring(textpos));
if (verbose) {
System.out.println(out);
}
}
if (!replace) {
m = cite.matcher(out);
if (m.find()) {
String s = m.group(1);
cites.add(s);
}
} else {
m = seccite.matcher(out);
int q = -1;
while (m.find(q+1)) {
String s = m.group(1);
String ref = m.group(2);
String num = labels.get(ref);
if (num == null) {
System.out.println("No match for " + ref);
break;
} else {
q = m.start();
int e = m.end();
String nn = "[Section " + num.substring(0,num.length()-1) + "](#" + ref + ")";
if (verbose) System.out.println(nn + " <== " + out.substring(q,e));
out = out.substring(0,q) + nn + out.substring(e);
m = seccite.matcher(out);
}
}
}
if (replace) w.print(out + newlineChar);
}
if (w != null) {
w.close();
f.close();
Path a = FileSystems.getDefault().getPath(file + ".tmp");
Path b = FileSystems.getDefault().getPath(file);
Files.move(a,b, StandardCopyOption.REPLACE_EXISTING);
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
if (verbose) System.out.println("Closing " + file);
}
}