68f5358833b144d2479b2b2bf4d14b5d9bcb0928
[nikiroo-utils.git] / src / be / nikiroo / utils / main / justify.java
1 package be.nikiroo.utils.main;
2
3 import java.util.AbstractMap;
4 import java.util.ArrayList;
5 import java.util.List;
6 import java.util.Map.Entry;
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?
41 // Content <-> Bullet spacing (null = no spacing)
42 List<Entry<String, String>> lines = new ArrayList<Entry<String, String>>();
43 Scanner scan = new Scanner(System.in);
44 scan.useDelimiter("\r\n|[\r\n]");
45 try {
46 StringBuilder previous = null;
47 StringBuilder tmp = new StringBuilder();
48 String previousItemBulletSpacing = null;
49 String itemBulletSpacing = null;
50 while (scan.hasNext()) {
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);
66 }
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 }
75
76 if (tmp.length() > 0) {
77 tmp.append(' ');
78 }
79 tmp.append(word.trim());
80 }
81 current = tmp.toString();
82
83 previousLineComplete = current.isEmpty()
84 || previousItemBulletSpacing != null
85 || (previous != null && isFullLine(previous));
86 }
87
88 if (previous == null) {
89 previous = new StringBuilder();
90 } else {
91 if (previousLineComplete) {
92 lines.add(new AbstractMap.SimpleEntry<String, String>(
93 previous.toString(), previousItemBulletSpacing));
94 previous.setLength(0);
95 previousItemBulletSpacing = itemBulletSpacing;
96 } else {
97 previous.append(' ');
98 }
99 }
100
101 previous.append(current);
102
103 }
104
105 if (previous != null) {
106 lines.add(new AbstractMap.SimpleEntry<String, String>(previous
107 .toString(), previousItemBulletSpacing));
108 }
109 } finally {
110 scan.close();
111 }
112
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 }
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) == '"'
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 "";
158 }
159 }