Skip to content

Commit 655305a

Browse files
committed
feat: Buffer.writer() can now handle many ansi sequences.
It also has a new `printBlock()` method. `Buffer` now also supports saving and restoring the buffer content.
1 parent 59a9b83 commit 655305a

7 files changed

Lines changed: 516 additions & 153 deletions

File tree

twinkle-ansi/src/main/java/org/codejive/twinkle/ansi/Ansi.java

Lines changed: 177 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,32 @@ public class Ansi {
1111
public static final String STYLE_DEFAULT_BACKGROUND =
1212
styles(DEFAULT_BACKGROUND); // Reset background color
1313

14+
/**
15+
* Returns the ANSI escape sequence for the given styles. The styles can be any combination of
16+
* the style constants defined in the Constants class, such as BOLD, UNDERLINED, or the output
17+
* of the color functions like foregroundArg(). The output is a string that can be used in the
18+
* console to apply the specified styles to the text that follows.
19+
*
20+
* @param styles the style codes to apply
21+
* @return the ANSI escape sequence for the given styles
22+
*/
1423
public static String styles(Object... styles) {
1524
if (styles == null || styles.length == 0) {
1625
return "";
1726
}
1827
return styles(new StringBuilder(), styles).toString();
1928
}
2029

30+
/**
31+
* Appends the ANSI escape sequence for the given styles to the provided Appendable. The styles
32+
* can be any combination of the style constants defined in the Constants class, such as BOLD,
33+
* UNDERLINED, or the output of the color functions like foregroundArg(). The output will be
34+
* passed to the provided Appendable.
35+
*
36+
* @param appendable the Appendable to which the ANSI escape sequence will be appended
37+
* @param styles the style codes to apply
38+
* @return the provided Appendable with the ANSI escape sequence appended
39+
*/
2140
public static Appendable styles(Appendable appendable, Object... styles) {
2241
if (styles == null || styles.length == 0) {
2342
return appendable;
@@ -37,88 +56,213 @@ public static Appendable styles(Appendable appendable, Object... styles) {
3756
return appendable;
3857
}
3958

40-
public static String foreground(int index) {
41-
return styles(FOREGROUND_BASE + index);
59+
/**
60+
* Returns the ANSI code for the given basic color. The index should be between 0-7. The output
61+
* is a string that can be used in the styles() method to create the final ANSI escape sequence.
62+
*
63+
* @param index the color index (0-7)
64+
* @return the ANSI code for the given basic color
65+
*/
66+
public static String foregroundArg(int index) {
67+
return String.valueOf(FOREGROUND_BASE + index);
4268
}
4369

44-
public static Appendable foreground(Appendable appendable, int index) {
45-
return styles(appendable, FOREGROUND_BASE + index);
46-
}
47-
48-
public static String foregroundDark(int index) {
70+
/**
71+
* Returns the ANSI code for the given dark color. The index should be between 0-7. The output
72+
* is a string that can be used in the styles() method to create the final ANSI escape sequence.
73+
*
74+
* @param index the color index (0-7)
75+
* @return the ANSI code for the given dark color
76+
*/
77+
public static String foregroundDarkArg(int index) {
4978
return String.valueOf(FOREGROUND_DARK_BASE + index);
5079
}
5180

52-
public static String foregroundBright(int index) {
81+
/**
82+
* Returns the ANSI code for the given bright color. The index should be between 0-7. The output
83+
* is a string that can be used in the styles() method to create the final ANSI escape sequence.
84+
*
85+
* @param index the color index (0-7)
86+
* @return the ANSI code for the given bright color
87+
*/
88+
public static String foregroundBrightArg(int index) {
5389
return String.valueOf(FOREGROUND_BRIGHT_BASE + index);
5490
}
5591

56-
public static String background(int index) {
92+
/**
93+
* Returns the ANSI code for the given basic background color. The index should be between 0-7.
94+
* The output is a string that can be used in the styles() method to create the final ANSI
95+
* escape sequence.
96+
*
97+
* @param index the color index (0-7)
98+
* @return the ANSI code for the given basic background color
99+
*/
100+
public static String backgroundArg(int index) {
57101
return String.valueOf(BACKGROUND_BASE + index);
58102
}
59103

60-
public static String backgroundDark(int index) {
104+
/**
105+
* Returns the ANSI code for the given dark background color. The index should be between 0-7.
106+
* The output is a string that can be used in the styles() method to create the final ANSI
107+
* escape sequence.
108+
*
109+
* @param index the color index (0-7)
110+
* @return the ANSI code for the given dark background color
111+
*/
112+
public static String backgroundDarkArg(int index) {
61113
return String.valueOf(BACKGROUND_DARK_BASE + index);
62114
}
63115

64-
public static String backgroundBright(int index) {
116+
/**
117+
* Returns the ANSI code for the given bright background color. The index should be between 0-7.
118+
* The output is a string that can be used in the styles() method to create the final ANSI
119+
* escape sequence.
120+
*
121+
* @param index the color index (0-7)
122+
* @return the ANSI code for the given bright background color
123+
*/
124+
public static String backgroundBrightArg(int index) {
65125
return String.valueOf(BACKGROUND_BRIGHT_BASE + index);
66126
}
67127

68-
public static String foregroundIndexed(int index) {
128+
/**
129+
* Returns the ANSI code for the given indexed foreground color. The index should be between
130+
* 0-255. The indexes 0-7 are the standard colors, 8-15 are the bright versions of the standard
131+
* colors, 16-231 are a 6x6x6 color cube, and 232-255 are a grayscale ramp. The output is a
132+
* string that can be used in the styles() method to create the final ANSI escape sequence.
133+
*
134+
* @param index the color index (0-255)
135+
* @return the ANSI code for the given indexed foreground color
136+
*/
137+
public static String foregroundIndexedArg(int index) {
69138
return FOREGROUND_COLORS + ";" + COLORS_INDEXED + ";" + index;
70139
}
71140

72-
public static String foregroundRgb(int r, int g, int b) {
73-
return FOREGROUND_COLORS + ";" + COLORS_RGB + ";" + r + ";" + g + ";" + b;
74-
}
75-
76-
public static String backgroundIndexed(int index) {
141+
/**
142+
* Returns the ANSI code for the given indexed background color. The index should be between
143+
* 0-255. The indexes 0-7 are the standard colors, 8-15 are the bright versions of the standard
144+
* colors, 16-231 are a 6x6x6 color cube, and 232-255 are a grayscale ramp. The output is a
145+
* string that can be used in the styles() method to create the final ANSI escape sequence.
146+
*
147+
* @param index the color index (0-255)
148+
* @return the ANSI code for the given indexed background color
149+
*/
150+
public static String backgroundIndexedArg(int index) {
77151
return BACKGROUND_COLORS + ";" + COLORS_INDEXED + ";" + index;
78152
}
79153

80-
public static String backgroundRgb(int r, int g, int b) {
81-
return BACKGROUND_COLORS + ";" + COLORS_RGB + ";" + r + ";" + g + ";" + b;
82-
}
83-
84-
public static String linkStart(String url) {
85-
return OSC + "8;;" + url + OSC_END;
154+
/**
155+
* Returns the ANSI code for the given RGB foreground color. The r, g, and b values should be
156+
* between 0-255. The output is a string that can be used in the styles() method to create the
157+
* final ANSI escape sequence.
158+
*
159+
* @param r the red component (0-255)
160+
* @param g the green component (0-255)
161+
* @param b the blue component (0-255)
162+
* @return the ANSI code for the given RGB foreground color
163+
*/
164+
public static String foregroundRgbArg(int r, int g, int b) {
165+
return FOREGROUND_COLORS + ";" + COLORS_RGB + ";" + r + ";" + g + ";" + b;
86166
}
87167

88-
public static String linkEnd() {
89-
return OSC + "8;;" + OSC_END;
168+
/**
169+
* Returns the ANSI code for the given RGB background color. The r, g, and b values should be
170+
* between 0-255. The output is a string that can be used in the styles() method to create the
171+
* final ANSI escape sequence.
172+
*
173+
* @param r the red component (0-255)
174+
* @param g the green component (0-255)
175+
* @param b the blue component (0-255)
176+
* @return the ANSI code for the given RGB background color
177+
*/
178+
public static String backgroundRgbArg(int r, int g, int b) {
179+
return BACKGROUND_COLORS + ";" + COLORS_RGB + ";" + r + ";" + g + ";" + b;
90180
}
91181

182+
/**
183+
* Returns the ANSI escape sequence for moving the cursor in the specified direction by 1. The
184+
* direction is determined by the command parameter, which can be one of the cursor movement
185+
* commands defined in the Constants class, such as CURSOR_UP, CURSOR_DOWN, etc.
186+
*
187+
* @param command the cursor movement command (e.g. CURSOR_UP, CURSOR_DOWN, etc.)
188+
* @return the ANSI escape sequence for moving the cursor
189+
*/
92190
public static String cursorMove(char command) {
93191
return cursorMove(command, 1);
94192
}
95193

194+
/**
195+
* Returns the ANSI escape sequence for moving the cursor in the specified direction by the
196+
* specified amount. The direction is determined by the command parameter, which can be one of
197+
* the cursor movement commands defined in the Constants class, such as CURSOR_UP, CURSOR_DOWN,
198+
* etc. The amount parameter specifies how many positions to move the cursor.
199+
*
200+
* @param command the cursor movement command (e.g. CURSOR_UP, CURSOR_DOWN, etc.)
201+
* @param amount the number of positions to move the cursor
202+
* @return the ANSI escape sequence for moving the cursor
203+
*/
96204
public static String cursorMove(char command, int amount) {
97205
return CSI + amount + command;
98206
}
99207

100208
public static String cursorPos(int row, int col) {
101-
return CSI + row + ";" + col + "H";
209+
return CSI + row + ";" + col + CURSOR_POSITION;
102210
}
103211

104212
public static String cursorHome() {
105-
return CSI + "H";
213+
return CSI + CURSOR_POSITION;
214+
}
215+
216+
public static String cursorToColumn(int col) {
217+
return CSI + col + CURSOR_COLUMN;
218+
}
219+
220+
public static String cursorUp(int amount) {
221+
return cursorMove(CURSOR_UP, amount);
106222
}
107223

108-
public static String hideCursor() {
109-
return CSI + "?25l";
224+
public static String cursorDown(int amount) {
225+
return cursorMove(CURSOR_DOWN, amount);
110226
}
111227

112-
public static String showCursor() {
113-
return CSI + "?25h";
228+
public static String cursorForward(int amount) {
229+
return cursorMove(CURSOR_FORWARD, amount);
230+
}
231+
232+
public static String cursorBackward(int amount) {
233+
return cursorMove(CURSOR_BACKWARD, amount);
234+
}
235+
236+
public static String cursorHide() {
237+
return CSI + CURSOR_HIDE;
238+
}
239+
240+
public static String cursorShow() {
241+
return CSI + CURSOR_SHOW;
242+
}
243+
244+
public static String cursorSave() {
245+
return "" + ESC + CURSOR_SAVE;
246+
}
247+
248+
public static String cursorRestore() {
249+
return "" + ESC + CURSOR_RESTORE;
114250
}
115251

116252
public static String clearScreen() {
117-
return CSI + "2J";
253+
return CSI + SCREEN_ERASE_FULL;
118254
}
119255

120256
public static String autoWrap(boolean enabled) {
121-
return CSI + (enabled ? "?7h" : "?7l");
257+
return CSI + (enabled ? LINE_WRAP_ON : LINE_WRAP_OFF);
258+
}
259+
260+
public static String linkStart(String url) {
261+
return OSC + "8;;" + url + OSC_END;
262+
}
263+
264+
public static String linkEnd() {
265+
return OSC + "8;;" + OSC_END;
122266
}
123267

124268
private Ansi() {}

twinkle-ansi/src/main/java/org/codejive/twinkle/ansi/Color.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -239,11 +239,11 @@ public String toAnsiBgArgs() {
239239
private static String fgAnsi(int index, Intensity intensity) {
240240
switch (intensity) {
241241
case normal:
242-
return Ansi.foreground(index);
242+
return Ansi.foregroundArg(index);
243243
case dark:
244-
return Ansi.foregroundDark(index);
244+
return Ansi.foregroundDarkArg(index);
245245
case bright:
246-
return Ansi.foregroundBright(index);
246+
return Ansi.foregroundBrightArg(index);
247247
default:
248248
throw new IllegalArgumentException("Unknown mode: " + intensity);
249249
}
@@ -252,11 +252,11 @@ private static String fgAnsi(int index, Intensity intensity) {
252252
private static String bgAnsi(int index, Intensity intensity) {
253253
switch (intensity) {
254254
case normal:
255-
return Ansi.background(index);
255+
return Ansi.backgroundArg(index);
256256
case dark:
257-
return Ansi.backgroundDark(index);
257+
return Ansi.backgroundDarkArg(index);
258258
case bright:
259-
return Ansi.backgroundBright(index);
259+
return Ansi.backgroundBrightArg(index);
260260
default:
261261
throw new IllegalArgumentException("Unknown mode: " + intensity);
262262
}
@@ -323,11 +323,11 @@ public String toAnsiBgArgs() {
323323
}
324324

325325
private static String fgAnsi(int index) {
326-
return Ansi.foregroundIndexed(index);
326+
return Ansi.foregroundIndexedArg(index);
327327
}
328328

329329
private static String bgAnsi(int index) {
330-
return Ansi.backgroundIndexed(index);
330+
return Ansi.backgroundIndexedArg(index);
331331
}
332332

333333
@Override
@@ -392,11 +392,11 @@ public String toAnsiBgArgs() {
392392
}
393393

394394
private static String fgAnsi(int r, int g, int b) {
395-
return Ansi.foregroundRgb(r, g, b);
395+
return Ansi.foregroundRgbArg(r, g, b);
396396
}
397397

398398
private static String bgAnsi(int r, int g, int b) {
399-
return Ansi.backgroundRgb(r, g, b);
399+
return Ansi.backgroundRgbArg(r, g, b);
400400
}
401401

402402
@Override

twinkle-ansi/src/main/java/org/codejive/twinkle/ansi/Constants.java

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,35 @@ public class Constants {
5252
public static final char CURSOR_UP = 'A';
5353
public static final char CURSOR_DOWN = 'B';
5454
public static final char CURSOR_FORWARD = 'C';
55-
public static final char CURSOR_BACK = 'D';
55+
public static final char CURSOR_BACKWARD = 'D';
5656
public static final char CURSOR_NEXT_LINE = 'E';
5757
public static final char CURSOR_PREV_LINE = 'F';
58-
public static final char CURSOR_HORIZONTAL_ABS = 'G';
58+
public static final char CURSOR_COLUMN = 'G';
5959
public static final char CURSOR_POSITION = 'H';
60+
public static final char CURSOR_POSITION_ALT = 'f';
61+
public static final char CURSOR_SAVE = '7'; // Note: ESC+7, not CSI+7 !
62+
public static final char CURSOR_RESTORE = '8'; // Note: ESC+8, not CSI+8 !
63+
public static final char CURSOR_UP_WITH_SCROLL = 'M'; // Note: ESC+M, not CSI+M !
64+
65+
public static final String CURSOR_HIDE = "?25l";
66+
public static final String CURSOR_SHOW = "?25h";
67+
68+
public static final String SCREEN_ERASE = "J"; // Same as SCREEN_ERASE_END
69+
public static final String SCREEN_ERASE_END = "0J";
70+
public static final String SCREEN_ERASE_START = "1J";
71+
public static final String SCREEN_ERASE_FULL = "2J";
72+
public static final String SCREEN_ERASE_SAVED_LINES = "3J";
73+
74+
public static final String SCREEN_SAVE = "?1049h";
75+
public static final String SCREEN_SAVE_ALT = "?47h";
76+
public static final String SCREEN_RESTORE = "?1049l";
77+
public static final String SCREEN_RESTORE_ALT = "?47l";
78+
79+
public static final String LINE_ERASE = "K"; // Same as LINE_ERASE_END
80+
public static final String LINE_ERASE_END = "0K";
81+
public static final String LINE_ERASE_START = "1K";
82+
public static final String LINE_ERASE_FULL = "2K";
83+
84+
public static final String LINE_WRAP_ON = "=7h";
85+
public static final String LINE_WRAP_OFF = "=7l";
6086
}

0 commit comments

Comments
 (0)