1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.fusesource.jansi;
20
21 import java.util.ArrayList;
22
23
24
25
26
27
28
29
30
31 @Deprecated
32 @SuppressWarnings("unused")
33 public class Ansi implements Appendable {
34
35 private static final char FIRST_ESC_CHAR = 27;
36 private static final char SECOND_ESC_CHAR = '[';
37
38
39
40
41 public enum Color {
42 BLACK(0, "BLACK"),
43 RED(1, "RED"),
44 GREEN(2, "GREEN"),
45 YELLOW(3, "YELLOW"),
46 BLUE(4, "BLUE"),
47 MAGENTA(5, "MAGENTA"),
48 CYAN(6, "CYAN"),
49 WHITE(7, "WHITE"),
50 DEFAULT(9, "DEFAULT");
51
52 private final int value;
53 private final String name;
54
55 Color(int index, String name) {
56 this.value = index;
57 this.name = name;
58 }
59
60 @Override
61 public String toString() {
62 return name;
63 }
64
65 public int value() {
66 return value;
67 }
68
69 public int fg() {
70 return value + 30;
71 }
72
73 public int bg() {
74 return value + 40;
75 }
76
77 public int fgBright() {
78 return value + 90;
79 }
80
81 public int bgBright() {
82 return value + 100;
83 }
84 }
85
86
87
88
89
90
91 public enum Attribute {
92 RESET(0, "RESET"),
93 INTENSITY_BOLD(1, "INTENSITY_BOLD"),
94 INTENSITY_FAINT(2, "INTENSITY_FAINT"),
95 ITALIC(3, "ITALIC_ON"),
96 UNDERLINE(4, "UNDERLINE_ON"),
97 BLINK_SLOW(5, "BLINK_SLOW"),
98 BLINK_FAST(6, "BLINK_FAST"),
99 NEGATIVE_ON(7, "NEGATIVE_ON"),
100 CONCEAL_ON(8, "CONCEAL_ON"),
101 STRIKETHROUGH_ON(9, "STRIKETHROUGH_ON"),
102 UNDERLINE_DOUBLE(21, "UNDERLINE_DOUBLE"),
103 INTENSITY_BOLD_OFF(22, "INTENSITY_BOLD_OFF"),
104 ITALIC_OFF(23, "ITALIC_OFF"),
105 UNDERLINE_OFF(24, "UNDERLINE_OFF"),
106 BLINK_OFF(25, "BLINK_OFF"),
107 NEGATIVE_OFF(27, "NEGATIVE_OFF"),
108 CONCEAL_OFF(28, "CONCEAL_OFF"),
109 STRIKETHROUGH_OFF(29, "STRIKETHROUGH_OFF");
110
111 private final int value;
112 private final String name;
113
114 Attribute(int index, String name) {
115 this.value = index;
116 this.name = name;
117 }
118
119 @Override
120 public String toString() {
121 return name;
122 }
123
124 public int value() {
125 return value;
126 }
127 }
128
129
130
131
132
133
134
135 public enum Erase {
136 FORWARD(0, "FORWARD"),
137 BACKWARD(1, "BACKWARD"),
138 ALL(2, "ALL");
139
140 private final int value;
141 private final String name;
142
143 Erase(int index, String name) {
144 this.value = index;
145 this.name = name;
146 }
147
148 @Override
149 public String toString() {
150 return name;
151 }
152
153 public int value() {
154 return value;
155 }
156 }
157
158 @FunctionalInterface
159 public interface Consumer {
160 void apply(Ansi ansi);
161 }
162
163 public static boolean isEnabled() {
164 return org.apache.maven.jline.MessageUtils.isColorEnabled() && org.jline.jansi.Ansi.isEnabled();
165 }
166
167 public static void setEnabled(final boolean flag) {
168 org.jline.jansi.Ansi.setEnabled(flag);
169 }
170
171 public static Ansi ansi() {
172 if (isEnabled()) {
173 return new Ansi();
174 } else {
175 return new NoAnsi();
176 }
177 }
178
179 public static Ansi ansi(StringBuilder builder) {
180 if (isEnabled()) {
181 return new Ansi(builder);
182 } else {
183 return new NoAnsi(builder);
184 }
185 }
186
187 public static Ansi ansi(int size) {
188 if (isEnabled()) {
189 return new Ansi(size);
190 } else {
191 return new NoAnsi(size);
192 }
193 }
194
195 private static class NoAnsi extends Ansi {
196 NoAnsi() {
197 super();
198 }
199
200 NoAnsi(int size) {
201 super(size);
202 }
203
204 NoAnsi(StringBuilder builder) {
205 super(builder);
206 }
207
208 @Override
209 public Ansi fg(Color color) {
210 return this;
211 }
212
213 @Override
214 public Ansi bg(Color color) {
215 return this;
216 }
217
218 @Override
219 public Ansi fgBright(Color color) {
220 return this;
221 }
222
223 @Override
224 public Ansi bgBright(Color color) {
225 return this;
226 }
227
228 @Override
229 public Ansi fg(int color) {
230 return this;
231 }
232
233 @Override
234 public Ansi fgRgb(int r, int g, int b) {
235 return this;
236 }
237
238 @Override
239 public Ansi bg(int color) {
240 return this;
241 }
242
243 @Override
244 public Ansi bgRgb(int r, int g, int b) {
245 return this;
246 }
247
248 @Override
249 public Ansi a(Attribute attribute) {
250 return this;
251 }
252
253 @Override
254 public Ansi cursor(int row, int column) {
255 return this;
256 }
257
258 @Override
259 public Ansi cursorToColumn(int x) {
260 return this;
261 }
262
263 @Override
264 public Ansi cursorUp(int y) {
265 return this;
266 }
267
268 @Override
269 public Ansi cursorRight(int x) {
270 return this;
271 }
272
273 @Override
274 public Ansi cursorDown(int y) {
275 return this;
276 }
277
278 @Override
279 public Ansi cursorLeft(int x) {
280 return this;
281 }
282
283 @Override
284 public Ansi cursorDownLine() {
285 return this;
286 }
287
288 @Override
289 public Ansi cursorDownLine(final int n) {
290 return this;
291 }
292
293 @Override
294 public Ansi cursorUpLine() {
295 return this;
296 }
297
298 @Override
299 public Ansi cursorUpLine(final int n) {
300 return this;
301 }
302
303 @Override
304 public Ansi eraseScreen() {
305 return this;
306 }
307
308 @Override
309 public Ansi eraseScreen(Erase kind) {
310 return this;
311 }
312
313 @Override
314 public Ansi eraseLine() {
315 return this;
316 }
317
318 @Override
319 public Ansi eraseLine(Erase kind) {
320 return this;
321 }
322
323 @Override
324 public Ansi scrollUp(int rows) {
325 return this;
326 }
327
328 @Override
329 public Ansi scrollDown(int rows) {
330 return this;
331 }
332
333 @Override
334 public Ansi saveCursorPosition() {
335 return this;
336 }
337
338 @Override
339 @Deprecated
340 public Ansi restorCursorPosition() {
341 return this;
342 }
343
344 @Override
345 public Ansi restoreCursorPosition() {
346 return this;
347 }
348
349 @Override
350 public Ansi reset() {
351 return this;
352 }
353 }
354
355 private final StringBuilder builder;
356 private final ArrayList<Integer> attributeOptions = new ArrayList<>(5);
357
358 public Ansi() {
359 this(new StringBuilder(80));
360 }
361
362 public Ansi(Ansi parent) {
363 this(new StringBuilder(parent.builder));
364 attributeOptions.addAll(parent.attributeOptions);
365 }
366
367 public Ansi(int size) {
368 this(new StringBuilder(size));
369 }
370
371 public Ansi(StringBuilder builder) {
372 this.builder = builder;
373 }
374
375 public Ansi fg(Color color) {
376 attributeOptions.add(color.fg());
377 return this;
378 }
379
380 public Ansi fg(int color) {
381 attributeOptions.add(38);
382 attributeOptions.add(5);
383 attributeOptions.add(color & 0xff);
384 return this;
385 }
386
387 public Ansi fgRgb(int color) {
388 return fgRgb(color >> 16, color >> 8, color);
389 }
390
391 public Ansi fgRgb(int r, int g, int b) {
392 attributeOptions.add(38);
393 attributeOptions.add(2);
394 attributeOptions.add(r & 0xff);
395 attributeOptions.add(g & 0xff);
396 attributeOptions.add(b & 0xff);
397 return this;
398 }
399
400 public Ansi fgBlack() {
401 return this.fg(Color.BLACK);
402 }
403
404 public Ansi fgBlue() {
405 return this.fg(Color.BLUE);
406 }
407
408 public Ansi fgCyan() {
409 return this.fg(Color.CYAN);
410 }
411
412 public Ansi fgDefault() {
413 return this.fg(Color.DEFAULT);
414 }
415
416 public Ansi fgGreen() {
417 return this.fg(Color.GREEN);
418 }
419
420 public Ansi fgMagenta() {
421 return this.fg(Color.MAGENTA);
422 }
423
424 public Ansi fgRed() {
425 return this.fg(Color.RED);
426 }
427
428 public Ansi fgYellow() {
429 return this.fg(Color.YELLOW);
430 }
431
432 public Ansi bg(Color color) {
433 attributeOptions.add(color.bg());
434 return this;
435 }
436
437 public Ansi bg(int color) {
438 attributeOptions.add(48);
439 attributeOptions.add(5);
440 attributeOptions.add(color & 0xff);
441 return this;
442 }
443
444 public Ansi bgRgb(int color) {
445 return bgRgb(color >> 16, color >> 8, color);
446 }
447
448 public Ansi bgRgb(int r, int g, int b) {
449 attributeOptions.add(48);
450 attributeOptions.add(2);
451 attributeOptions.add(r & 0xff);
452 attributeOptions.add(g & 0xff);
453 attributeOptions.add(b & 0xff);
454 return this;
455 }
456
457 public Ansi bgCyan() {
458 return this.bg(Color.CYAN);
459 }
460
461 public Ansi bgDefault() {
462 return this.bg(Color.DEFAULT);
463 }
464
465 public Ansi bgGreen() {
466 return this.bg(Color.GREEN);
467 }
468
469 public Ansi bgMagenta() {
470 return this.bg(Color.MAGENTA);
471 }
472
473 public Ansi bgRed() {
474 return this.bg(Color.RED);
475 }
476
477 public Ansi bgYellow() {
478 return this.bg(Color.YELLOW);
479 }
480
481 public Ansi fgBright(Color color) {
482 attributeOptions.add(color.fgBright());
483 return this;
484 }
485
486 public Ansi fgBrightBlack() {
487 return this.fgBright(Color.BLACK);
488 }
489
490 public Ansi fgBrightBlue() {
491 return this.fgBright(Color.BLUE);
492 }
493
494 public Ansi fgBrightCyan() {
495 return this.fgBright(Color.CYAN);
496 }
497
498 public Ansi fgBrightDefault() {
499 return this.fgBright(Color.DEFAULT);
500 }
501
502 public Ansi fgBrightGreen() {
503 return this.fgBright(Color.GREEN);
504 }
505
506 public Ansi fgBrightMagenta() {
507 return this.fgBright(Color.MAGENTA);
508 }
509
510 public Ansi fgBrightRed() {
511 return this.fgBright(Color.RED);
512 }
513
514 public Ansi fgBrightYellow() {
515 return this.fgBright(Color.YELLOW);
516 }
517
518 public Ansi bgBright(Color color) {
519 attributeOptions.add(color.bgBright());
520 return this;
521 }
522
523 public Ansi bgBrightCyan() {
524 return this.bgBright(Color.CYAN);
525 }
526
527 public Ansi bgBrightDefault() {
528 return this.bgBright(Color.DEFAULT);
529 }
530
531 public Ansi bgBrightGreen() {
532 return this.bgBright(Color.GREEN);
533 }
534
535 public Ansi bgBrightMagenta() {
536 return this.bgBright(Color.MAGENTA);
537 }
538
539 public Ansi bgBrightRed() {
540 return this.bgBright(Color.RED);
541 }
542
543 public Ansi bgBrightYellow() {
544 return this.bgBright(Color.YELLOW);
545 }
546
547 public Ansi a(Attribute attribute) {
548 attributeOptions.add(attribute.value());
549 return this;
550 }
551
552
553
554
555
556
557
558
559
560 public Ansi cursor(final int row, final int column) {
561 return appendEscapeSequence('H', Math.max(1, row), Math.max(1, column));
562 }
563
564
565
566
567
568
569
570
571 public Ansi cursorToColumn(final int x) {
572 return appendEscapeSequence('G', Math.max(1, x));
573 }
574
575
576
577
578
579
580
581 public Ansi cursorUp(final int y) {
582 return y > 0 ? appendEscapeSequence('A', y) : y < 0 ? cursorDown(-y) : this;
583 }
584
585
586
587
588
589
590
591 public Ansi cursorDown(final int y) {
592 return y > 0 ? appendEscapeSequence('B', y) : y < 0 ? cursorUp(-y) : this;
593 }
594
595
596
597
598
599
600
601 public Ansi cursorRight(final int x) {
602 return x > 0 ? appendEscapeSequence('C', x) : x < 0 ? cursorLeft(-x) : this;
603 }
604
605
606
607
608
609
610
611 public Ansi cursorLeft(final int x) {
612 return x > 0 ? appendEscapeSequence('D', x) : x < 0 ? cursorRight(-x) : this;
613 }
614
615
616
617
618
619
620
621
622
623
624 public Ansi cursorMove(final int x, final int y) {
625 return cursorRight(x).cursorDown(y);
626 }
627
628
629
630
631
632
633 public Ansi cursorDownLine() {
634 return appendEscapeSequence('E');
635 }
636
637
638
639
640
641
642
643
644 public Ansi cursorDownLine(final int n) {
645 return n < 0 ? cursorUpLine(-n) : appendEscapeSequence('E', n);
646 }
647
648
649
650
651
652
653 public Ansi cursorUpLine() {
654 return appendEscapeSequence('F');
655 }
656
657
658
659
660
661
662
663
664 public Ansi cursorUpLine(final int n) {
665 return n < 0 ? cursorDownLine(-n) : appendEscapeSequence('F', n);
666 }
667
668 public Ansi eraseScreen() {
669 return appendEscapeSequence('J', Erase.ALL.value());
670 }
671
672 public Ansi eraseScreen(final Erase kind) {
673 return appendEscapeSequence('J', kind.value());
674 }
675
676 public Ansi eraseLine() {
677 return appendEscapeSequence('K');
678 }
679
680 public Ansi eraseLine(final Erase kind) {
681 return appendEscapeSequence('K', kind.value());
682 }
683
684 public Ansi scrollUp(final int rows) {
685 if (rows == Integer.MIN_VALUE) {
686 return scrollDown(Integer.MAX_VALUE);
687 }
688 return rows > 0 ? appendEscapeSequence('S', rows) : rows < 0 ? scrollDown(-rows) : this;
689 }
690
691 public Ansi scrollDown(final int rows) {
692 if (rows == Integer.MIN_VALUE) {
693 return scrollUp(Integer.MAX_VALUE);
694 }
695 return rows > 0 ? appendEscapeSequence('T', rows) : rows < 0 ? scrollUp(-rows) : this;
696 }
697
698 @Deprecated
699 public Ansi restorCursorPosition() {
700 return restoreCursorPosition();
701 }
702
703 public Ansi saveCursorPosition() {
704 saveCursorPositionSCO();
705 return saveCursorPositionDEC();
706 }
707
708
709 public Ansi saveCursorPositionSCO() {
710 return appendEscapeSequence('s');
711 }
712
713
714 public Ansi saveCursorPositionDEC() {
715 builder.append(FIRST_ESC_CHAR);
716 builder.append('7');
717 return this;
718 }
719
720 public Ansi restoreCursorPosition() {
721 restoreCursorPositionSCO();
722 return restoreCursorPositionDEC();
723 }
724
725
726 public Ansi restoreCursorPositionSCO() {
727 return appendEscapeSequence('u');
728 }
729
730
731 public Ansi restoreCursorPositionDEC() {
732 builder.append(FIRST_ESC_CHAR);
733 builder.append('8');
734 return this;
735 }
736
737 public Ansi reset() {
738 return a(Attribute.RESET);
739 }
740
741 public Ansi bold() {
742 return a(Attribute.INTENSITY_BOLD);
743 }
744
745 public Ansi boldOff() {
746 return a(Attribute.INTENSITY_BOLD_OFF);
747 }
748
749 public Ansi a(String value) {
750 flushAttributes();
751 builder.append(value);
752 return this;
753 }
754
755 public Ansi a(boolean value) {
756 flushAttributes();
757 builder.append(value);
758 return this;
759 }
760
761 public Ansi a(char value) {
762 flushAttributes();
763 builder.append(value);
764 return this;
765 }
766
767 public Ansi a(char[] value, int offset, int len) {
768 flushAttributes();
769 builder.append(value, offset, len);
770 return this;
771 }
772
773 public Ansi a(char[] value) {
774 flushAttributes();
775 builder.append(value);
776 return this;
777 }
778
779 public Ansi a(CharSequence value, int start, int end) {
780 flushAttributes();
781 builder.append(value, start, end);
782 return this;
783 }
784
785 public Ansi a(CharSequence value) {
786 flushAttributes();
787 builder.append(value);
788 return this;
789 }
790
791 public Ansi a(double value) {
792 flushAttributes();
793 builder.append(value);
794 return this;
795 }
796
797 public Ansi a(float value) {
798 flushAttributes();
799 builder.append(value);
800 return this;
801 }
802
803 public Ansi a(int value) {
804 flushAttributes();
805 builder.append(value);
806 return this;
807 }
808
809 public Ansi a(long value) {
810 flushAttributes();
811 builder.append(value);
812 return this;
813 }
814
815 public Ansi a(Object value) {
816 flushAttributes();
817 builder.append(value);
818 return this;
819 }
820
821 public Ansi a(StringBuffer value) {
822 flushAttributes();
823 builder.append(value);
824 return this;
825 }
826
827 public Ansi newline() {
828 flushAttributes();
829 builder.append(System.lineSeparator());
830 return this;
831 }
832
833 public Ansi format(String pattern, Object... args) {
834 flushAttributes();
835 builder.append(String.format(pattern, args));
836 return this;
837 }
838
839
840
841
842
843
844
845
846 public Ansi apply(Consumer fun) {
847 fun.apply(this);
848 return this;
849 }
850
851
852
853
854
855
856
857
858
859 public Ansi render(final String text) {
860 a(new org.jline.jansi.Ansi().render(text).toString());
861 return this;
862 }
863
864
865
866
867
868
869
870
871
872
873 public Ansi render(final String text, Object... args) {
874 a(String.format(new org.jline.jansi.Ansi().render(text).toString(), args));
875 return this;
876 }
877
878 @Override
879 public String toString() {
880 flushAttributes();
881 return builder.toString();
882 }
883
884
885
886
887
888 private Ansi appendEscapeSequence(char command) {
889 flushAttributes();
890 builder.append(FIRST_ESC_CHAR);
891 builder.append(SECOND_ESC_CHAR);
892 builder.append(command);
893 return this;
894 }
895
896 private Ansi appendEscapeSequence(char command, int option) {
897 flushAttributes();
898 builder.append(FIRST_ESC_CHAR);
899 builder.append(SECOND_ESC_CHAR);
900 builder.append(option);
901 builder.append(command);
902 return this;
903 }
904
905 private Ansi appendEscapeSequence(char command, Object... options) {
906 flushAttributes();
907 return doAppendEscapeSequence(command, options);
908 }
909
910 private void flushAttributes() {
911 if (attributeOptions.isEmpty()) {
912 return;
913 }
914 if (attributeOptions.size() == 1 && attributeOptions.get(0) == 0) {
915 builder.append(FIRST_ESC_CHAR);
916 builder.append(SECOND_ESC_CHAR);
917 builder.append('m');
918 } else {
919 doAppendEscapeSequence('m', attributeOptions.toArray());
920 }
921 attributeOptions.clear();
922 }
923
924 private Ansi doAppendEscapeSequence(char command, Object... options) {
925 builder.append(FIRST_ESC_CHAR);
926 builder.append(SECOND_ESC_CHAR);
927 int size = options.length;
928 for (int i = 0; i < size; i++) {
929 if (i != 0) {
930 builder.append(';');
931 }
932 if (options[i] != null) {
933 builder.append(options[i]);
934 }
935 }
936 builder.append(command);
937 return this;
938 }
939
940 @Override
941 public Ansi append(CharSequence csq) {
942 builder.append(csq);
943 return this;
944 }
945
946 @Override
947 public Ansi append(CharSequence csq, int start, int end) {
948 builder.append(csq, start, end);
949 return this;
950 }
951
952 @Override
953 public Ansi append(char c) {
954 builder.append(c);
955 return this;
956 }
957 }