1 /*
2  * Copyright (c) 2002-2019, the original author or authors.
3  *
4  * This software is distributable under the BSD license. See the terms of the
5  * BSD license in the documentation provided with this software.
6  *
7  * https://opensource.org/licenses/BSD-3-Clause
8  */
9 package jdk.internal.org.jline.utils;
10 
11 import java.io.BufferedReader;
12 import java.io.IOError;
13 import java.io.IOException;
14 import java.io.InputStream;
15 import java.nio.charset.StandardCharsets;
16 import java.util.*;
17 import java.util.function.Supplier;
18 import java.util.regex.Matcher;
19 import java.util.regex.Pattern;
20 import java.util.stream.Collectors;
21 
22 /**
23  * Infocmp helper methods.
24  *
25  * @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a>
26  */
27 public final class InfoCmp {
28 
29     private static final Map<String, Object> CAPS = new HashMap<>();
30 
InfoCmp()31     private InfoCmp() {
32     }
33 
34     @SuppressWarnings("unused")
35     public enum Capability {
36 
37         auto_left_margin,           // auto_left_margin, bw, bw
38         auto_right_margin,          // auto_right_margin, am, am
39         back_color_erase,           // back_color_erase, bce, ut
40         can_change,                 // can_change, ccc, cc
41         ceol_standout_glitch,       // ceol_standout_glitch, xhp, xs
42         col_addr_glitch,            // col_addr_glitch, xhpa, YA
43         cpi_changes_res,            // cpi_changes_res, cpix, YF
44         cr_cancels_micro_mode,      // cr_cancels_micro_mode, crxm, YB
45         dest_tabs_magic_smso,       // dest_tabs_magic_smso, xt, xt
46         eat_newline_glitch,         // eat_newline_glitch, xenl, xn
47         erase_overstrike,           // erase_overstrike, eo, eo
48         generic_type,               // generic_type, gn, gn
49         hard_copy,                  // hard_copy, hc, hc
50         hard_cursor,                // hard_cursor, chts, HC
51         has_meta_key,               // has_meta_key, km, km
52         has_print_wheel,            // has_print_wheel, daisy, YC
53         has_status_line,            // has_status_line, hs, hs
54         hue_lightness_saturation,   // hue_lightness_saturation, hls, hl
55         insert_null_glitch,         // insert_null_glitch, in, in
56         lpi_changes_res,            // lpi_changes_res, lpix, YG
57         memory_above,               // memory_above, da, da
58         memory_below,               // memory_below, db, db
59         move_insert_mode,           // move_insert_mode, mir, mi
60         move_standout_mode,         // move_standout_mode, msgr, ms
61         needs_xon_xoff,             // needs_xon_xoff, nxon, nx
62         no_esc_ctlc,                // no_esc_ctlc, xsb, xb
63         no_pad_char,                // no_pad_char, npc, NP
64         non_dest_scroll_region,     // non_dest_scroll_region, ndscr, ND
65         non_rev_rmcup,              // non_rev_rmcup, nrrmc, NR
66         over_strike,                // over_strike, os, os
67         prtr_silent,                // prtr_silent, mc5i, 5i
68         row_addr_glitch,            // row_addr_glitch, xvpa, YD
69         semi_auto_right_margin,     // semi_auto_right_margin, sam, YE
70         status_line_esc_ok,         // status_line_esc_ok, eslok, es
71         tilde_glitch,               // tilde_glitch, hz, hz
72         transparent_underline,      // transparent_underline, ul, ul
73         xon_xoff,                   // xon_xoff, xon, xo
74         columns,                    // columns, cols, co
75         init_tabs,                  // init_tabs, it, it
76         label_height,               // label_height, lh, lh
77         label_width,                // label_width, lw, lw
78         lines,                      // lines, lines, li
79         lines_of_memory,            // lines_of_memory, lm, lm
80         magic_cookie_glitch,        // magic_cookie_glitch, xmc, sg
81         max_attributes,             // max_attributes, ma, ma
82         max_colors,                 // max_colors, colors, Co
83         max_pairs,                  // max_pairs, pairs, pa
84         maximum_windows,            // maximum_windows, wnum, MW
85         no_color_video,             // no_color_video, ncv, NC
86         num_labels,                 // num_labels, nlab, Nl
87         padding_baud_rate,          // padding_baud_rate, pb, pb
88         virtual_terminal,           // virtual_terminal, vt, vt
89         width_status_line,          // width_status_line, wsl, ws
90         bit_image_entwining,        // bit_image_entwining, bitwin, Yo
91         bit_image_type,             // bit_image_type, bitype, Yp
92         buffer_capacity,            // buffer_capacity, bufsz, Ya
93         buttons,                    // buttons, btns, BT
94         dot_horz_spacing,           // dot_horz_spacing, spinh, Yc
95         dot_vert_spacing,           // dot_vert_spacing, spinv, Yb
96         max_micro_address,          // max_micro_address, maddr, Yd
97         max_micro_jump,             // max_micro_jump, mjump, Ye
98         micro_col_size,             // micro_col_size, mcs, Yf
99         micro_line_size,            // micro_line_size, mls, Yg
100         number_of_pins,             // number_of_pins, npins, Yh
101         output_res_char,            // output_res_char, orc, Yi
102         output_res_horz_inch,       // output_res_horz_inch, orhi, Yk
103         output_res_line,            // output_res_line, orl, Yj
104         output_res_vert_inch,       // output_res_vert_inch, orvi, Yl
105         print_rate,                 // print_rate, cps, Ym
106         wide_char_size,             // wide_char_size, widcs, Yn
107         acs_chars,                  // acs_chars, acsc, ac
108         back_tab,                   // back_tab, cbt, bt
109         bell,                       // bell, bel, bl
110         carriage_return,            // carriage_return, cr, cr
111         change_char_pitch,          // change_char_pitch, cpi, ZA
112         change_line_pitch,          // change_line_pitch, lpi, ZB
113         change_res_horz,            // change_res_horz, chr, ZC
114         change_res_vert,            // change_res_vert, cvr, ZD
115         change_scroll_region,       // change_scroll_region, csr, cs
116         char_padding,               // char_padding, rmp, rP
117         clear_all_tabs,             // clear_all_tabs, tbc, ct
118         clear_margins,              // clear_margins, mgc, MC
119         clear_screen,               // clear_screen, clear, cl
120         clr_bol,                    // clr_bol, el1, cb
121         clr_eol,                    // clr_eol, el, ce
122         clr_eos,                    // clr_eos, ed, cd
123         column_address,             // column_address, hpa, ch
124         command_character,          // command_character, cmdch, CC
125         create_window,              // create_window, cwin, CW
126         cursor_address,             // cursor_address, cup, cm
127         cursor_down,                // cursor_down, cud1, do
128         cursor_home,                // cursor_home, home, ho
129         cursor_invisible,           // cursor_invisible, civis, vi
130         cursor_left,                // cursor_left, cub1, le
131         cursor_mem_address,         // cursor_mem_address, mrcup, CM
132         cursor_normal,              // cursor_normal, cnorm, ve
133         cursor_right,               // cursor_right, cuf1, nd
134         cursor_to_ll,               // cursor_to_ll, ll, ll
135         cursor_up,                  // cursor_up, cuu1, up
136         cursor_visible,             // cursor_visible, cvvis, vs
137         define_char,                // define_char, defc, ZE
138         delete_character,           // delete_character, dch1, dc
139         delete_line,                // delete_line, dl1, dl
140         dial_phone,                 // dial_phone, dial, DI
141         dis_status_line,            // dis_status_line, dsl, ds
142         display_clock,              // display_clock, dclk, DK
143         down_half_line,             // down_half_line, hd, hd
144         ena_acs,                    // ena_acs, enacs, eA
145         enter_alt_charset_mode,     // enter_alt_charset_mode, smacs, as
146         enter_am_mode,              // enter_am_mode, smam, SA
147         enter_blink_mode,           // enter_blink_mode, blink, mb
148         enter_bold_mode,            // enter_bold_mode, bold, md
149         enter_ca_mode,              // enter_ca_mode, smcup, ti
150         enter_delete_mode,          // enter_delete_mode, smdc, dm
151         enter_dim_mode,             // enter_dim_mode, dim, mh
152         enter_doublewide_mode,      // enter_doublewide_mode, swidm, ZF
153         enter_draft_quality,        // enter_draft_quality, sdrfq, ZG
154         enter_insert_mode,          // enter_insert_mode, smir, im
155         enter_italics_mode,         // enter_italics_mode, sitm, ZH
156         enter_leftward_mode,        // enter_leftward_mode, slm, ZI
157         enter_micro_mode,           // enter_micro_mode, smicm, ZJ
158         enter_near_letter_quality,  // enter_near_letter_quality, snlq, ZK
159         enter_normal_quality,       // enter_normal_quality, snrmq, ZL
160         enter_protected_mode,       // enter_protected_mode, prot, mp
161         enter_reverse_mode,         // enter_reverse_mode, rev, mr
162         enter_secure_mode,          // enter_secure_mode, invis, mk
163         enter_shadow_mode,          // enter_shadow_mode, sshm, ZM
164         enter_standout_mode,        // enter_standout_mode, smso, so
165         enter_subscript_mode,       // enter_subscript_mode, ssubm, ZN
166         enter_superscript_mode,     // enter_superscript_mode, ssupm, ZO
167         enter_underline_mode,       // enter_underline_mode, smul, us
168         enter_upward_mode,          // enter_upward_mode, sum, ZP
169         enter_xon_mode,             // enter_xon_mode, smxon, SX
170         erase_chars,                // erase_chars, ech, ec
171         exit_alt_charset_mode,      // exit_alt_charset_mode, rmacs, ae
172         exit_am_mode,               // exit_am_mode, rmam, RA
173         exit_attribute_mode,        // exit_attribute_mode, sgr0, me
174         exit_ca_mode,               // exit_ca_mode, rmcup, te
175         exit_delete_mode,           // exit_delete_mode, rmdc, ed
176         exit_doublewide_mode,       // exit_doublewide_mode, rwidm, ZQ
177         exit_insert_mode,           // exit_insert_mode, rmir, ei
178         exit_italics_mode,          // exit_italics_mode, ritm, ZR
179         exit_leftward_mode,         // exit_leftward_mode, rlm, ZS
180         exit_micro_mode,            // exit_micro_mode, rmicm, ZT
181         exit_shadow_mode,           // exit_shadow_mode, rshm, ZU
182         exit_standout_mode,         // exit_standout_mode, rmso, se
183         exit_subscript_mode,        // exit_subscript_mode, rsubm, ZV
184         exit_superscript_mode,      // exit_superscript_mode, rsupm, ZW
185         exit_underline_mode,        // exit_underline_mode, rmul, ue
186         exit_upward_mode,           // exit_upward_mode, rum, ZX
187         exit_xon_mode,              // exit_xon_mode, rmxon, RX
188         fixed_pause,                // fixed_pause, pause, PA
189         flash_hook,                 // flash_hook, hook, fh
190         flash_screen,               // flash_screen, flash, vb
191         form_feed,                  // form_feed, ff, ff
192         from_status_line,           // from_status_line, fsl, fs
193         goto_window,                // goto_window, wingo, WG
194         hangup,                     // hangup, hup, HU
195         init_1string,               // init_1string, is1, i1
196         init_2string,               // init_2string, is2, is
197         init_3string,               // init_3string, is3, i3
198         init_file,                  // init_file, if, if
199         init_prog,                  // init_prog, iprog, iP
200         initialize_color,           // initialize_color, initc, Ic
201         initialize_pair,            // initialize_pair, initp, Ip
202         insert_character,           // insert_character, ich1, ic
203         insert_line,                // insert_line, il1, al
204         insert_padding,             // insert_padding, ip, ip
205         key_a1,                     // key_a1, ka1, K1
206         key_a3,                     // key_a3, ka3, K3
207         key_b2,                     // key_b2, kb2, K2
208         key_backspace,              // key_backspace, kbs, kb
209         key_beg,                    // key_beg, kbeg, @1
210         key_btab,                   // key_btab, kcbt, kB
211         key_c1,                     // key_c1, kc1, K4
212         key_c3,                     // key_c3, kc3, K5
213         key_cancel,                 // key_cancel, kcan, @2
214         key_catab,                  // key_catab, ktbc, ka
215         key_clear,                  // key_clear, kclr, kC
216         key_close,                  // key_close, kclo, @3
217         key_command,                // key_command, kcmd, @4
218         key_copy,                   // key_copy, kcpy, @5
219         key_create,                 // key_create, kcrt, @6
220         key_ctab,                   // key_ctab, kctab, kt
221         key_dc,                     // key_dc, kdch1, kD
222         key_dl,                     // key_dl, kdl1, kL
223         key_down,                   // key_down, kcud1, kd
224         key_eic,                    // key_eic, krmir, kM
225         key_end,                    // key_end, kend, @7
226         key_enter,                  // key_enter, kent, @8
227         key_eol,                    // key_eol, kel, kE
228         key_eos,                    // key_eos, ked, kS
229         key_exit,                   // key_exit, kext, @9
230         key_f0,                     // key_f0, kf0, k0
231         key_f1,                     // key_f1, kf1, k1
232         key_f10,                    // key_f10, kf10, k;
233         key_f11,                    // key_f11, kf11, F1
234         key_f12,                    // key_f12, kf12, F2
235         key_f13,                    // key_f13, kf13, F3
236         key_f14,                    // key_f14, kf14, F4
237         key_f15,                    // key_f15, kf15, F5
238         key_f16,                    // key_f16, kf16, F6
239         key_f17,                    // key_f17, kf17, F7
240         key_f18,                    // key_f18, kf18, F8
241         key_f19,                    // key_f19, kf19, F9
242         key_f2,                     // key_f2, kf2, k2
243         key_f20,                    // key_f20, kf20, FA
244         key_f21,                    // key_f21, kf21, FB
245         key_f22,                    // key_f22, kf22, FC
246         key_f23,                    // key_f23, kf23, FD
247         key_f24,                    // key_f24, kf24, FE
248         key_f25,                    // key_f25, kf25, FF
249         key_f26,                    // key_f26, kf26, FG
250         key_f27,                    // key_f27, kf27, FH
251         key_f28,                    // key_f28, kf28, FI
252         key_f29,                    // key_f29, kf29, FJ
253         key_f3,                     // key_f3, kf3, k3
254         key_f30,                    // key_f30, kf30, FK
255         key_f31,                    // key_f31, kf31, FL
256         key_f32,                    // key_f32, kf32, FM
257         key_f33,                    // key_f33, kf33, FN
258         key_f34,                    // key_f34, kf34, FO
259         key_f35,                    // key_f35, kf35, FP
260         key_f36,                    // key_f36, kf36, FQ
261         key_f37,                    // key_f37, kf37, FR
262         key_f38,                    // key_f38, kf38, FS
263         key_f39,                    // key_f39, kf39, FT
264         key_f4,                     // key_f4, kf4, k4
265         key_f40,                    // key_f40, kf40, FU
266         key_f41,                    // key_f41, kf41, FV
267         key_f42,                    // key_f42, kf42, FW
268         key_f43,                    // key_f43, kf43, FX
269         key_f44,                    // key_f44, kf44, FY
270         key_f45,                    // key_f45, kf45, FZ
271         key_f46,                    // key_f46, kf46, Fa
272         key_f47,                    // key_f47, kf47, Fb
273         key_f48,                    // key_f48, kf48, Fc
274         key_f49,                    // key_f49, kf49, Fd
275         key_f5,                     // key_f5, kf5, k5
276         key_f50,                    // key_f50, kf50, Fe
277         key_f51,                    // key_f51, kf51, Ff
278         key_f52,                    // key_f52, kf52, Fg
279         key_f53,                    // key_f53, kf53, Fh
280         key_f54,                    // key_f54, kf54, Fi
281         key_f55,                    // key_f55, kf55, Fj
282         key_f56,                    // key_f56, kf56, Fk
283         key_f57,                    // key_f57, kf57, Fl
284         key_f58,                    // key_f58, kf58, Fm
285         key_f59,                    // key_f59, kf59, Fn
286         key_f6,                     // key_f6, kf6, k6
287         key_f60,                    // key_f60, kf60, Fo
288         key_f61,                    // key_f61, kf61, Fp
289         key_f62,                    // key_f62, kf62, Fq
290         key_f63,                    // key_f63, kf63, Fr
291         key_f7,                     // key_f7, kf7, k7
292         key_f8,                     // key_f8, kf8, k8
293         key_f9,                     // key_f9, kf9, k9
294         key_find,                   // key_find, kfnd, @0
295         key_help,                   // key_help, khlp, %1
296         key_home,                   // key_home, khome, kh
297         key_ic,                     // key_ic, kich1, kI
298         key_il,                     // key_il, kil1, kA
299         key_left,                   // key_left, kcub1, kl
300         key_ll,                     // key_ll, kll, kH
301         key_mark,                   // key_mark, kmrk, %2
302         key_message,                // key_message, kmsg, %3
303         key_move,                   // key_move, kmov, %4
304         key_next,                   // key_next, knxt, %5
305         key_npage,                  // key_npage, knp, kN
306         key_open,                   // key_open, kopn, %6
307         key_options,                // key_options, kopt, %7
308         key_ppage,                  // key_ppage, kpp, kP
309         key_previous,               // key_previous, kprv, %8
310         key_print,                  // key_print, kprt, %9
311         key_redo,                   // key_redo, krdo, %0
312         key_reference,              // key_reference, kref, &1
313         key_refresh,                // key_refresh, krfr, &2
314         key_replace,                // key_replace, krpl, &3
315         key_restart,                // key_restart, krst, &4
316         key_resume,                 // key_resume, kres, &5
317         key_right,                  // key_right, kcuf1, kr
318         key_save,                   // key_save, ksav, &6
319         key_sbeg,                   // key_sbeg, kBEG, &9
320         key_scancel,                // key_scancel, kCAN, &0
321         key_scommand,               // key_scommand, kCMD, *1
322         key_scopy,                  // key_scopy, kCPY, *2
323         key_screate,                // key_screate, kCRT, *3
324         key_sdc,                    // key_sdc, kDC, *4
325         key_sdl,                    // key_sdl, kDL, *5
326         key_select,                 // key_select, kslt, *6
327         key_send,                   // key_send, kEND, *7
328         key_seol,                   // key_seol, kEOL, *8
329         key_sexit,                  // key_sexit, kEXT, *9
330         key_sf,                     // key_sf, kind, kF
331         key_sfind,                  // key_sfind, kFND, *0
332         key_shelp,                  // key_shelp, kHLP, #1
333         key_shome,                  // key_shome, kHOM, #2
334         key_sic,                    // key_sic, kIC, #3
335         key_sleft,                  // key_sleft, kLFT, #4
336         key_smessage,               // key_smessage, kMSG, %a
337         key_smove,                  // key_smove, kMOV, %b
338         key_snext,                  // key_snext, kNXT, %c
339         key_soptions,               // key_soptions, kOPT, %d
340         key_sprevious,              // key_sprevious, kPRV, %e
341         key_sprint,                 // key_sprint, kPRT, %f
342         key_sr,                     // key_sr, kri, kR
343         key_sredo,                  // key_sredo, kRDO, %g
344         key_sreplace,               // key_sreplace, kRPL, %h
345         key_sright,                 // key_sright, kRIT, %i
346         key_srsume,                 // key_srsume, kRES, %j
347         key_ssave,                  // key_ssave, kSAV, !1
348         key_ssuspend,               // key_ssuspend, kSPD, !2
349         key_stab,                   // key_stab, khts, kT
350         key_sundo,                  // key_sundo, kUND, !3
351         key_suspend,                // key_suspend, kspd, &7
352         key_undo,                   // key_undo, kund, &8
353         key_up,                     // key_up, kcuu1, ku
354         keypad_local,               // keypad_local, rmkx, ke
355         keypad_xmit,                // keypad_xmit, smkx, ks
356         lab_f0,                     // lab_f0, lf0, l0
357         lab_f1,                     // lab_f1, lf1, l1
358         lab_f10,                    // lab_f10, lf10, la
359         lab_f2,                     // lab_f2, lf2, l2
360         lab_f3,                     // lab_f3, lf3, l3
361         lab_f4,                     // lab_f4, lf4, l4
362         lab_f5,                     // lab_f5, lf5, l5
363         lab_f6,                     // lab_f6, lf6, l6
364         lab_f7,                     // lab_f7, lf7, l7
365         lab_f8,                     // lab_f8, lf8, l8
366         lab_f9,                     // lab_f9, lf9, l9
367         label_format,               // label_format, fln, Lf
368         label_off,                  // label_off, rmln, LF
369         label_on,                   // label_on, smln, LO
370         meta_off,                   // meta_off, rmm, mo
371         meta_on,                    // meta_on, smm, mm
372         micro_column_address,       // micro_column_address, mhpa, ZY
373         micro_down,                 // micro_down, mcud1, ZZ
374         micro_left,                 // micro_left, mcub1, Za
375         micro_right,                // micro_right, mcuf1, Zb
376         micro_row_address,          // micro_row_address, mvpa, Zc
377         micro_up,                   // micro_up, mcuu1, Zd
378         newline,                    // newline, nel, nw
379         order_of_pins,              // order_of_pins, porder, Ze
380         orig_colors,                // orig_colors, oc, oc
381         orig_pair,                  // orig_pair, op, op
382         pad_char,                   // pad_char, pad, pc
383         parm_dch,                   // parm_dch, dch, DC
384         parm_delete_line,           // parm_delete_line, dl, DL
385         parm_down_cursor,           // parm_down_cursor, cud, DO
386         parm_down_micro,            // parm_down_micro, mcud, Zf
387         parm_ich,                   // parm_ich, ich, IC
388         parm_index,                 // parm_index, indn, SF
389         parm_insert_line,           // parm_insert_line, il, AL
390         parm_left_cursor,           // parm_left_cursor, cub, LE
391         parm_left_micro,            // parm_left_micro, mcub, Zg
392         parm_right_cursor,          // parm_right_cursor, cuf, RI
393         parm_right_micro,           // parm_right_micro, mcuf, Zh
394         parm_rindex,                // parm_rindex, rin, SR
395         parm_up_cursor,             // parm_up_cursor, cuu, UP
396         parm_up_micro,              // parm_up_micro, mcuu, Zi
397         pkey_key,                   // pkey_key, pfkey, pk
398         pkey_local,                 // pkey_local, pfloc, pl
399         pkey_xmit,                  // pkey_xmit, pfx, px
400         plab_norm,                  // plab_norm, pln, pn
401         print_screen,               // print_screen, mc0, ps
402         prtr_non,                   // prtr_non, mc5p, pO
403         prtr_off,                   // prtr_off, mc4, pf
404         prtr_on,                    // prtr_on, mc5, po
405         pulse,                      // pulse, pulse, PU
406         quick_dial,                 // quick_dial, qdial, QD
407         remove_clock,               // remove_clock, rmclk, RC
408         repeat_char,                // repeat_char, rep, rp
409         req_for_input,              // req_for_input, rfi, RF
410         reset_1string,              // reset_1string, rs1, r1
411         reset_2string,              // reset_2string, rs2, r2
412         reset_3string,              // reset_3string, rs3, r3
413         reset_file,                 // reset_file, rf, rf
414         restore_cursor,             // restore_cursor, rc, rc
415         row_address,                // row_address, vpa, cv
416         save_cursor,                // save_cursor, sc, sc
417         scroll_forward,             // scroll_forward, ind, sf
418         scroll_reverse,             // scroll_reverse, ri, sr
419         select_char_set,            // select_char_set, scs, Zj
420         set_attributes,             // set_attributes, sgr, sa
421         set_background,             // set_background, setb, Sb
422         set_bottom_margin,          // set_bottom_margin, smgb, Zk
423         set_bottom_margin_parm,     // set_bottom_margin_parm, smgbp, Zl
424         set_clock,                  // set_clock, sclk, SC
425         set_color_pair,             // set_color_pair, scp, sp
426         set_foreground,             // set_foreground, setf, Sf
427         set_left_margin,            // set_left_margin, smgl, ML
428         set_left_margin_parm,       // set_left_margin_parm, smglp, Zm
429         set_right_margin,           // set_right_margin, smgr, MR
430         set_right_margin_parm,      // set_right_margin_parm, smgrp, Zn
431         set_tab,                    // set_tab, hts, st
432         set_top_margin,             // set_top_margin, smgt, Zo
433         set_top_margin_parm,        // set_top_margin_parm, smgtp, Zp
434         set_window,                 // set_window, wind, wi
435         start_bit_image,            // start_bit_image, sbim, Zq
436         start_char_set_def,         // start_char_set_def, scsd, Zr
437         stop_bit_image,             // stop_bit_image, rbim, Zs
438         stop_char_set_def,          // stop_char_set_def, rcsd, Zt
439         subscript_characters,       // subscript_characters, subcs, Zu
440         superscript_characters,     // superscript_characters, supcs, Zv
441         tab,                        // tab, ht, ta
442         these_cause_cr,             // these_cause_cr, docr, Zw
443         to_status_line,             // to_status_line, tsl, ts
444         tone,                       // tone, tone, TO
445         underline_char,             // underline_char, uc, uc
446         up_half_line,               // up_half_line, hu, hu
447         user0,                      // user0, u0, u0
448         user1,                      // user1, u1, u1
449         user2,                      // user2, u2, u2
450         user3,                      // user3, u3, u3
451         user4,                      // user4, u4, u4
452         user5,                      // user5, u5, u5
453         user6,                      // user6, u6, u6
454         user7,                      // user7, u7, u7
455         user8,                      // user8, u8, u8
456         user9,                      // user9, u9, u9
457         wait_tone,                  // wait_tone, wait, WA
458         xoff_character,             // xoff_character, xoffc, XF
459         xon_character,              // xon_character, xonc, XN
460         zero_motion,                // zero_motion, zerom, Zx
461         alt_scancode_esc,           // alt_scancode_esc, scesa, S8
462         bit_image_carriage_return,  // bit_image_carriage_return, bicr, Yv
463         bit_image_newline,          // bit_image_newline, binel, Zz
464         bit_image_repeat,           // bit_image_repeat, birep, Xy
465         char_set_names,             // char_set_names, csnm, Zy
466         code_set_init,              // code_set_init, csin, ci
467         color_names,                // color_names, colornm, Yw
468         define_bit_image_region,    // define_bit_image_region, defbi, Yx
469         device_type,                // device_type, devt, dv
470         display_pc_char,            // display_pc_char, dispc, S1
471         end_bit_image_region,       // end_bit_image_region, endbi, Yy
472         enter_pc_charset_mode,      // enter_pc_charset_mode, smpch, S2
473         enter_scancode_mode,        // enter_scancode_mode, smsc, S4
474         exit_pc_charset_mode,       // exit_pc_charset_mode, rmpch, S3
475         exit_scancode_mode,         // exit_scancode_mode, rmsc, S5
476         get_mouse,                  // get_mouse, getm, Gm
477         key_mouse,                  // key_mouse, kmous, Km
478         mouse_info,                 // mouse_info, minfo, Mi
479         pc_term_options,            // pc_term_options, pctrm, S6
480         pkey_plab,                  // pkey_plab, pfxl, xl
481         req_mouse_pos,              // req_mouse_pos, reqmp, RQ
482         scancode_escape,            // scancode_escape, scesc, S7
483         set0_des_seq,               // set0_des_seq, s0ds, s0
484         set1_des_seq,               // set1_des_seq, s1ds, s1
485         set2_des_seq,               // set2_des_seq, s2ds, s2
486         set3_des_seq,               // set3_des_seq, s3ds, s3
487         set_a_background,           // set_a_background, setab, AB
488         set_a_foreground,           // set_a_foreground, setaf, AF
489         set_color_band,             // set_color_band, setcolor, Yz
490         set_lr_margin,              // set_lr_margin, smglr, ML
491         set_page_length,            // set_page_length, slines, YZ
492         set_tb_margin,              // set_tb_margin, smgtb, MT
493         enter_horizontal_hl_mode,   // enter_horizontal_hl_mode, ehhlm, Xh
494         enter_left_hl_mode,         // enter_left_hl_mode, elhlm, Xl
495         enter_low_hl_mode,          // enter_low_hl_mode, elohlm, Xo
496         enter_right_hl_mode,        // enter_right_hl_mode, erhlm, Xr
497         enter_top_hl_mode,          // enter_top_hl_mode, ethlm, Xt
498         enter_vertical_hl_mode,     // enter_vertical_hl_mode, evhlm, Xv
499         set_a_attributes,           // set_a_attributes, sgr1, sA
500         set_pglen_inch,             // set_pglen_inch, slength, sL)
501         ;
502 
getNames()503         public String[] getNames() {
504             return getCapabilitiesByName().entrySet().stream()
505                     .filter(e -> e.getValue() == this)
506                     .map(Map.Entry::getValue)
507                     .toArray(String[]::new);
508         }
509 
byName(String name)510         public static Capability byName(String name) {
511             return getCapabilitiesByName().get(name);
512         }
513     }
514 
getCapabilitiesByName()515     public static Map<String, Capability> getCapabilitiesByName() {
516         Map<String, Capability> capabilities = new LinkedHashMap<>();
517         try (InputStream is = InfoCmp.class.getResourceAsStream("capabilities.txt");
518              BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
519             br.lines().map(String::trim)
520                     .filter(s -> !s.startsWith("#"))
521                     .filter(s -> !s.isEmpty())
522                     .forEach(s -> {
523                         String[] names = s.split(", ");
524                         Capability cap = Enum.valueOf(Capability.class, names[0]);
525                         capabilities.put(names[0], cap);
526                         capabilities.put(names[1], cap);
527                     });
528             return capabilities;
529         } catch (IOException e) {
530             throw new IOError(e);
531         }
532     }
533 
setDefaultInfoCmp(String terminal, String caps)534     public static void setDefaultInfoCmp(String terminal, String caps) {
535         CAPS.putIfAbsent(terminal, caps);
536     }
537 
setDefaultInfoCmp(String terminal, Supplier<String> caps)538     public static void setDefaultInfoCmp(String terminal, Supplier<String> caps) {
539         CAPS.putIfAbsent(terminal, caps);
540     }
541 
getInfoCmp( String terminal )542     public static String getInfoCmp(
543             String terminal
544     ) throws IOException, InterruptedException {
545         String caps = getLoadedInfoCmp(terminal);
546         if (caps == null) {
547             Process p = new ProcessBuilder(OSUtils.INFOCMP_COMMAND, terminal).start();
548             caps = ExecHelper.waitAndCapture(p);
549             CAPS.put(terminal, caps);
550         }
551         return caps;
552     }
553 
getLoadedInfoCmp(String terminal)554     public static String getLoadedInfoCmp(String terminal) {
555         Object caps = CAPS.get(terminal);
556         if (caps instanceof Supplier) {
557             caps = ((Supplier) caps).get();
558         }
559         return (String) caps;
560     }
561 
parseInfoCmp( String capabilities, Set<Capability> bools, Map<Capability, Integer> ints, Map<Capability, String> strings )562     public static void parseInfoCmp(
563             String capabilities,
564             Set<Capability> bools,
565             Map<Capability, Integer> ints,
566             Map<Capability, String> strings
567     ) {
568         Map<String, Capability> capsByName = getCapabilitiesByName();
569         String[] lines = capabilities.split("\n");
570         for (int i = 1; i < lines.length; i++) {
571             Matcher m = Pattern.compile("\\s*(([^,]|\\\\,)+)\\s*[,$]").matcher(lines[i]);
572             while (m.find()) {
573                 String cap = m.group(1);
574                 if (cap.contains("#")) {
575                     int index = cap.indexOf('#');
576                     String key = cap.substring(0, index);
577                     String val = cap.substring(index + 1);
578                     int iVal;
579                     if ("0".equals(val)) {
580                         iVal = 0;
581                     } else if (val.startsWith("0x")) {
582                         iVal = Integer.parseInt(val.substring(2), 16);
583                     } else if (val.startsWith("0")) {
584                         iVal = Integer.parseInt(val.substring(1), 8);
585                     } else {
586                         iVal = Integer.parseInt(val);
587                     }
588                     Capability c = capsByName.get(key);
589                     if (c != null) {
590                         ints.put(c, iVal);
591                     }
592                 } else if (cap.contains("=")) {
593                     int index = cap.indexOf('=');
594                     String key = cap.substring(0, index);
595                     String val = cap.substring(index + 1);
596                     Capability c = capsByName.get(key);
597                     if (c != null) {
598                         strings.put(c, val);
599                     }
600                 } else {
601                     Capability c = capsByName.get(cap);
602                     if (c != null) {
603                         bools.add(c);
604                     }
605                 }
606             }
607         }
608     }
609 
loadDefaultInfoCmp(String name)610     static String loadDefaultInfoCmp(String name) {
611         try (InputStream is = InfoCmp.class.getResourceAsStream(name + ".caps");
612              BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
613             return br.lines().collect(Collectors.joining("\n", "", "\n"));
614         } catch (IOException e) {
615             throw new IOError(e);
616         }
617     }
618 
619     static {
620         for (String s : Arrays.asList("dumb", "dumb-color", "ansi", "xterm", "xterm-256color",
621                 "windows", "windows-256color", "windows-conemu", "windows-vtp",
622                 "screen", "screen-256color")) {
setDefaultInfoCmp(s, () -> loadDefaultInfoCmp(s))623             setDefaultInfoCmp(s, () -> loadDefaultInfoCmp(s));
624         }
625     }
626 
627 }
628