Commit | Line | Data |
---|---|---|
9e50696e NR |
1 | package be.nikiroo.utils.main; |
2 | ||
a5d976cd | 3 | import java.util.AbstractMap; |
9e50696e NR |
4 | import java.util.ArrayList; |
5 | import java.util.List; | |
a5d976cd | 6 | import java.util.Map.Entry; |
9e50696e NR |
7 | import java.util.Scanner; |
8 | ||
9 | import be.nikiroo.utils.StringUtils; | |
10 | import be.nikiroo.utils.StringUtils.Alignment; | |
11 | ||
12 | /** | |
13 | * Text justification (left, right, center, justify). | |
14 | * | |
15 | * @author niki | |
16 | */ | |
17 | public class justify { | |
18 | /** | |
19 | * Syntax: $0 ([left|right|center|justify]) (max width) | |
20 | * <p> | |
21 | * <ul> | |
22 | * <li>mode: left, right, center or full justification (defaults to left)</li> | |
23 | * <li>max width: the maximum width of a line, or "" for "no maximum" | |
24 | * (defaults to "no maximum")</li> | |
25 | * </ul> | |
26 | * | |
27 | * @param args | |
28 | */ | |
29 | public static void main(String[] args) { | |
30 | int width = -1; | |
31 | StringUtils.Alignment align = Alignment.LEFT; | |
32 | ||
33 | if (args.length >= 1) { | |
34 | align = Alignment.valueOf(args[0].toUpperCase()); | |
35 | } | |
36 | if (args.length >= 2) { | |
37 | width = Integer.parseInt(args[1]); | |
38 | } | |
39 | ||
40 | // TODO: move to utils? | |
a5d976cd NR |
41 | // Content <-> Bullet spacing (null = no spacing) |
42 | List<Entry<String, String>> lines = new ArrayList<Entry<String, String>>(); | |
9e50696e | 43 | Scanner scan = new Scanner(System.in); |
67e9a06e | 44 | scan.useDelimiter("\r\n|[\r\n]"); |
9e50696e NR |
45 | try { |
46 | StringBuilder previous = null; | |
47 | StringBuilder tmp = new StringBuilder(); | |
a5d976cd NR |
48 | String previousItemBulletSpacing = null; |
49 | String itemBulletSpacing = null; | |
9e50696e | 50 | while (scan.hasNext()) { |
a5d976cd NR |
51 | boolean previousLineComplete = true; |
52 | ||
53 | String current = scan.next().replace("\t", " "); | |
54 | itemBulletSpacing = getItemSpacing(current); | |
55 | boolean bullet = isItemLine(current); | |
56 | if ((previousItemBulletSpacing == null || itemBulletSpacing | |
57 | .length() <= previousItemBulletSpacing.length()) | |
58 | && !bullet) { | |
59 | itemBulletSpacing = null; | |
60 | } | |
61 | ||
62 | if (itemBulletSpacing != null) { | |
63 | current = current.trim(); | |
64 | if (!current.isEmpty() && bullet) { | |
65 | current = current.substring(1); | |
9e50696e | 66 | } |
a5d976cd NR |
67 | current = current.trim(); |
68 | previousLineComplete = bullet; | |
69 | } else { | |
70 | tmp.setLength(0); | |
71 | for (String word : current.split(" ")) { | |
72 | if (word.isEmpty()) { | |
73 | continue; | |
74 | } | |
9e50696e | 75 | |
a5d976cd NR |
76 | if (tmp.length() > 0) { |
77 | tmp.append(' '); | |
78 | } | |
79 | tmp.append(word.trim()); | |
9e50696e | 80 | } |
a5d976cd NR |
81 | current = tmp.toString(); |
82 | ||
83 | previousLineComplete = current.isEmpty() | |
84 | || previousItemBulletSpacing != null | |
85 | || (previous != null && isFullLine(previous)); | |
9e50696e | 86 | } |
9e50696e NR |
87 | |
88 | if (previous == null) { | |
89 | previous = new StringBuilder(); | |
90 | } else { | |
a5d976cd NR |
91 | if (previousLineComplete) { |
92 | lines.add(new AbstractMap.SimpleEntry<String, String>( | |
93 | previous.toString(), previousItemBulletSpacing)); | |
9e50696e | 94 | previous.setLength(0); |
a5d976cd | 95 | previousItemBulletSpacing = itemBulletSpacing; |
9e50696e NR |
96 | } else { |
97 | previous.append(' '); | |
98 | } | |
99 | } | |
100 | ||
101 | previous.append(current); | |
a5d976cd | 102 | |
9e50696e NR |
103 | } |
104 | ||
105 | if (previous != null) { | |
a5d976cd NR |
106 | lines.add(new AbstractMap.SimpleEntry<String, String>(previous |
107 | .toString(), previousItemBulletSpacing)); | |
9e50696e NR |
108 | } |
109 | } finally { | |
110 | scan.close(); | |
111 | } | |
112 | ||
a5d976cd NR |
113 | for (Entry<String, String> line : lines) { |
114 | String content = line.getKey(); | |
115 | String spacing = line.getValue(); | |
116 | ||
117 | String bullet = "- "; | |
118 | if (spacing == null) { | |
119 | bullet = ""; | |
120 | spacing = ""; | |
121 | } | |
122 | ||
123 | if (spacing.length() > width + 3) { | |
124 | spacing = ""; | |
125 | } | |
126 | ||
127 | for (String subline : StringUtils.justifyText(content, width | |
128 | - (spacing.length() + bullet.length()), align)) { | |
129 | System.out.println(spacing + bullet + subline); | |
130 | if (!bullet.isEmpty()) { | |
131 | bullet = " "; | |
132 | } | |
9e50696e NR |
133 | } |
134 | } | |
135 | } | |
136 | ||
137 | static private boolean isFullLine(StringBuilder line) { | |
138 | return line.length() == 0 // | |
139 | || line.charAt(line.length() - 1) == '.' | |
140 | || line.charAt(line.length() - 1) == '"' | |
a5d976cd NR |
141 | || line.charAt(line.length() - 1) == 'ยป'; |
142 | } | |
143 | ||
144 | static private boolean isItemLine(String line) { | |
145 | String spacing = getItemSpacing(line); | |
146 | return spacing != null && line.charAt(spacing.length()) == '-'; | |
147 | } | |
148 | ||
149 | static private String getItemSpacing(String line) { | |
150 | int i; | |
151 | for (i = 0; i < line.length(); i++) { | |
152 | if (line.charAt(i) != ' ') { | |
153 | return line.substring(0, i); | |
154 | } | |
155 | } | |
156 | ||
157 | return ""; | |
9e50696e NR |
158 | } |
159 | } |