diff options
Diffstat (limited to 'tui/termfo/term.h.zsh')
| -rwxr-xr-x | tui/termfo/term.h.zsh | 427 |
1 files changed, 427 insertions, 0 deletions
diff --git a/tui/termfo/term.h.zsh b/tui/termfo/term.h.zsh new file mode 100755 index 0000000..aba713b --- /dev/null +++ b/tui/termfo/term.h.zsh @@ -0,0 +1,427 @@ +#!/usr/bin/env zsh +[ "${ZSH_VERSION:-}" = "" ] && echo >&2 "Only works with zsh" && exit 1 # Just in case people type "bash term.h.zsh". +setopt err_exit no_unset no_clobber pipefail + +# TODO: also look at capalias and infoalias in Caps-ncurses. +# +# https://github.com/benhoyt/goawk can run from within Go; that might actually +# be quite nice for this and removes the dependency on zsh and awk. + +src=${1:-~/ncurses} +if [[ ! -d $src ]]; then + print >&2 "ncurses source not in $src; can't generate term.h.go" + print >&2 'Usage: term.h.zsh [source-tree]' + exit 1 +fi + +main() { + mkdir -p caps scaps keys + caps >|caps/caps.go + scaps >|scaps/scaps.go + caps_table >|caps/table.go + keys >|keys/keys.go + gofmt -w caps/caps.go scaps/scaps.go caps/table.go keys/keys.go +} + +funs=$(<<'EOF' + function ucfirst(s) { + return toupper(substr(s, 1, 1)) substr(s, 2) + } + + function camelCase(s) { + while (i = index(s, "_")) + s = substr(s, 0, i-1) toupper(substr(s, i+1, 1)) substr(s, i+2) + return ucfirst(s) + } +EOF +) + +# Print package header. +# pkg pkgname [pkgcomment] [add-version] [import] +pkg() { + print '// Code generated by term.h.zsh; DO NOT EDIT.\n' + (( $# > 1 && ${#2:-} > 0 )) && print "// Package $1 $2" + print "package $1\n" + (( $# > 2 )) && print $3 + if (( $# < 4 )); then + print '// CursesVersion is the version of curses this data was generated with, as [implementation]-[version].' + awk '{printf "const CursesVersion = `ncurses-%s.%s`\n\n", $2, $3 }' $src/VERSION + fi + return 0 +} + +cap_ignore=$(<<-'EOF' + BEGIN { + ignore["tilde_glitch"] = 1 # Hacks for ancient hardware terms. + ignore["eat_newline_glitch"] = 1 + ignore["insert_null_glitch"] = 1 + ignore["col_addr_glitch"] = 1 + ignore["row_addr_glitch"] = 1 + ignore["magic_cookie_glitch"] = 1 + ignore["magic_cookie_glitch_ul"] = 1 + ignore["ceol_standout_glitch"] = 1 + ignore["hard_cursor"] = 1 + ignore["no_esc_ctlc"] = 1 + ignore["new_line_delay"] = 1 + ignore["carriage_return_delay"] = 1 + ignore["no_correctly_working_cr"] = 1 + ignore["crt_no_scrolling"] = 1 + ignore["linefeed_if_not_lf"] = 1 + ignore["backspace_if_not_bs"] = 1 + ignore["linefeed_is_newline"] = 1 + ignore["backspace_delay"] = 1 + ignore["horizontal_tab_delay"] = 1 + ignore["other_non_function_keys"] = 1 + ignore["number_of_function_keys"] = 1 + ignore["arrow_key_map"] = 1 + ignore["return_does_clr_eol"] = 1 + ignore["dest_tabs_magic_smso"] = 1 + ignore["non_dest_scroll_region"] = 1 + ignore["non_rev_rmcup"] = 1 + ignore["padding_baud_rate"] = 1 + ignore["has_print_wheel"] = 1 # No vaguely modern terminal has this. + ignore["set_left_margin"] = 1 + ignore["set_right_margin"] = 1 + ignore["set_bottom_margin"] = 1 + ignore["set_bottom_margin_parm"] = 1 + ignore["set_top_margin"] = 1 + ignore["set_top_margin_parm"] = 1 + ignore["set_tb_margin"] = 1 + ignore["order_of_pins"] = 1 + ignore["lines_of_memory"] = 1 + ignore["output_res_char"] = 1 + ignore["output_res_line"] = 1 + ignore["wide_char_size"] = 1 + ignore["enter_doublewide_mode"] = 1 + ignore["exit_doublewide_mode"] = 1 + ignore["hue_lightness_saturation"] = 1 + ignore["fixed_pause"] = 1 + ignore["hangup"] = 1 + ignore["dial_phone"] = 1 + ignore["pulse"] = 1 + ignore["flash_hook"] = 1 + ignore["quick_dial"] = 1 + ignore["wait_tone"] = 1 + ignore["tone"] = 1 + ignore["set_clock"] = 1 + ignore["display_clock"] = 1 + ignore["remove_clock"] = 1 + ignore["create_window"] = 1 + ignore["goto_window"] = 1 + ignore["set_window"] = 1 + ignore["maximum_windows"] = 1 + ignore["number_of_pins"] = 1 + ignore["plab_norm"] = 1 + ignore["label_format"] = 1 + ignore["num_labels"] = 1 + ignore["label_height"] = 1 + ignore["label_width"] = 1 + ignore["label_on"] = 1 + ignore["label_off"] = 1 + ignore["lab_f0"] = 1 + ignore["lab_f1"] = 1 + ignore["lab_f10"] = 1 + ignore["lab_f2"] = 1 + ignore["lab_f3"] = 1 + ignore["lab_f4"] = 1 + ignore["lab_f5"] = 1 + ignore["lab_f6"] = 1 + ignore["lab_f7"] = 1 + ignore["lab_f8"] = 1 + ignore["lab_f9"] = 1 + ignore["semi_auto_right_margin"] = 1 + ignore["enter_draft_quality"] = 1 + ignore["enter_near_letter_quality"] = 1 + ignore["enter_normal_quality"] = 1 + ignore["generic_type"] = 1 + ignore["set_left_margin_parm"] = 1 # Setting margins kind-of in e.g. xterm, but it's pretty broken and useless. + ignore["set_right_margin_parm"] = 1 + ignore["set_lr_margin"] = 1 + ignore["clear_margins"] = 1 + ignore["auto_left_margin"] = 1 # I can't figure out what these "automatic margins" do, or how they work. So I'm going to guess it's not really useful. + ignore["auto_right_margin"] = 1 + ignore["enter_am_mode"] = 1 + ignore["exit_am_mode"] = 1 + ignore["cr_cancels_micro_mode"] = 1 # "Micro mode", whatever that is; only on QNX 4. + ignore["max_micro_address"] = 1 + ignore["max_micro_jump"] = 1 + ignore["micro_col_size"] = 1 + ignore["micro_line_size"] = 1 + ignore["enter_micro_mode"] = 1 + ignore["exit_micro_mode"] = 1 + ignore["micro_column_address"] = 1 + ignore["micro_down"] = 1 + ignore["micro_left"] = 1 + ignore["micro_right"] = 1 + ignore["micro_row_address"] = 1 + ignore["micro_up"] = 1 + ignore["parm_down_micro"] = 1 + ignore["parm_left_micro"] = 1 + ignore["parm_right_micro"] = 1 + ignore["parm_up_micro"] = 1 + ignore["prtr_silent"] = 1 # Printer support; no one has that. + ignore["prtr_non"] = 1 + ignore["set_pglen_inch"] = 1 + ignore["change_char_pitch"] = 1 + ignore["change_line_pitch"] = 1 + ignore["output_res_horz_inch"] = 1 + ignore["output_res_vert_inch"] = 1 + ignore["dot_vert_spacing"] = 1 + ignore["dot_horz_spacing"] = 1 + ignore["buffer_capacity"] = 1 + ignore["print_rate"] = 1 + ignore["print_screen"] = 1 + ignore["prtr_off"] = 1 + ignore["prtr_on"] = 1 + ignore["prtr_non"] = 1 + ignore["start_bit_image"] = 1 + ignore["stop_bit_image"] = 1 + ignore["these_cause_cr"] = 1 + ignore["hard_copy"] = 1 + ignore["bit_image_entwining"] = 1 # Not supported by anything. + ignore["bit_image_type"] = 1 + ignore["bit_image_repeat"] = 1 + ignore["bit_image_newline"] = 1 + ignore["bit_image_carriage_return"] = 1 + ignore["define_bit_image_region"] = 1 + ignore["end_bit_image_region"] = 1 + + # dsl / disable_status_line + # kitty = clear window title + + names[""] = "" + } +EOF +) + +# Generate caps/caps.go +caps() { + pkg caps 'contains a list of all terminfo capabilities.' + cat <<-'EOF' + // Cap represents a capability as listed in a terminfo file. + type Cap struct { + Short string // Short terminfo name + Long string // Longer variable name from term.h + Desc string // Description from terminfo(5) + } + EOF + + print "var (" + awk <$src/include/Caps "$funs $cap_ignore $(<<-'EOF' + /^[^#]/ { + # TODO: breaks too much + # if (ignore[$1] != "" || match($1, "^key_")) + # next + name = names[$1] + if (name == "") + name = camelCase($1) + printf "\t%s = &Cap{`%s`, `%s`, `%s", name, $2, $1, $8 + for (i=9; i<=NF; i++) + printf " %s", $i + print "`}" + } + EOF + )" + + print '\n// Extentions' + awk <$src/include/Caps-ncurses "$funs $cap_ignore $(<<-'EOF' + $1 == "used_by" { used_by = $2 } + $1 == "userdef" { + # Some entries are listed more than once (xm and RGB). + # TODO: append the descriptions? + if (uniq[$2]) + next + uniq[$2] = 1 + + printf "\t%s = &Cap{`%s`, `%s`, `%s", camelCase($2), $2, $1, $5 + for (i=6; i<=NF; i++) + printf " %s", $i + printf " (%s)`}\n", used_by + } + EOF + )" + print ")" +} + +# Generage scaps/scaps.go +scaps() { + pkg scaps 'contains a list of all terminfo capabilities.' 'import "zgo.at/termfo/caps"' + + print "var (" + awk <$src/include/Caps "$funs $(<<-'EOF' + /^[^#]/ { + print "\t" ucfirst($2) " = caps." camelCase($1) + } + EOF + )" + + print '\n// Extentions' + awk <$src/include/Caps-ncurses "$funs $(<<-'EOF' + $1 == "used_by" { used_by = $2 } + $1 == "userdef" { + if (uniq[$2]) + next + uniq[$2] = 1 + print "\t" ucfirst($2) " = caps." ucfirst($2) + } + EOF + )" + print ")" +} + +# Generate caps/table.go +caps_table() { + pkg caps '' '' 'no-version' + print "var unused *Cap = nil\n" + + for t in bool num str; do + tu=${t[1]:u}${t[2,-1]} + print "var Table${tu}s = []*Cap{" + awk <$src/include/Caps "$funs $cap_ignore ${$(<<-'EOF' + /^[^#]/ && $3 == "TYPE" { + name = names[$1] + if (name == "") + name = camelCase($1) + # TODO: breaks too much + # if (ignore[$1] != "" || match($1, "^key_")) + # name = "unused" + print name "," + } + EOF + )//TYPE/$t}" + + print '\n// Extensions' + awk <$src/include/Caps-ncurses "$funs $cap_ignore ${$(<<-'EOF' + $1 == "userdef" && $3 == "TYPE" { + print camelCase($2) "," + } + EOF + )//TYPE/$t}" + print "}\n" + done +} + +# List all key caps. +keys() { + pkg keys '' 'import "zgo.at/termfo/caps"' + # pkg keys '' '' + + awk <$src/include/Caps "$funs $(<<-'EOF' + BEGIN { + print "// Keys maps caps.Cap to Key constants" + print "var Keys = map[*caps.Cap]Key{" + # print "var Keys = map[Key]string{" + i = -1 + + # Obscure keys present on very old devices; most people have neither + # heard nor used any of these devices or keys, so there's not much + # point including them. Can still use the termCaps if you really + # want to, just don't need a shortcut for them. + # + # Some of these are still useful codes to send, but they're just not + # keys (anymore). + # + # Use ./cmd/termfo to print terminals which have a certain capability. + ignore["Catab"] = 1 + ignore["Ctab"] = 1 + ignore["Dl"] = 1; ignore["Sdl"] = 1 + ignore["Eic"] = 1 + ignore["Eol"] = 1; ignore["Seol"] = 1 + ignore["Eos"] = 1 + ignore["Il"] = 1 + ignore["Sr"] = 1 + ignore["Sf"] = 1 + ignore["Clear"] = 1 + ignore["F0"] = 1 + ignore["Ll"] = 1 + ignore["Stab"] = 1 + ignore["A1"] = 1 + ignore["A3"] = 1 + ignore["B2"] = 1 + ignore["C1"] = 1 + ignore["C3"] = 1 + ignore["Beg"] = 1; ignore["Sbeg"] = 1 + ignore["Cancel"] = 1; ignore["Scancel"] = 1 + ignore["Close"] = 1; ignore["Close"] = 1 + ignore["Command"] = 1; ignore["Scommand"] = 1 + ignore["Copy"] = 1; ignore["Scopy"] = 1 + ignore["Create"] = 1; ignore["Screate"] = 1 + ignore["Exit"] = 1; ignore["Sexit"] = 1 + ignore["Find"] = 1; ignore["Sfind"] = 1 + ignore["Help"] = 1; ignore["Shelp"] = 1 + ignore["Mark"] = 1; ignore["Smark"] = 1 + ignore["Message"] = 1; ignore["Smessage"] = 1 + ignore["Move"] = 1; ignore["Smove"] = 1 + ignore["Next"] = 1; ignore["Snext"] = 1 + ignore["Open"] = 1; ignore["Sopen"] = 1 + ignore["Options"] = 1; ignore["Soptions"] = 1 + ignore["Save"] = 1; ignore["Ssave"] = 1 + ignore["Previous"] = 1; ignore["Sprevious"] = 1 + ignore["Print"] = 1; ignore["Sprint"] = 1 + ignore["Redo"] = 1; ignore["Sredo"] = 1 + ignore["Reference"] = 1; ignore["sreference"] = 1 + ignore["Refresh"] = 1; ignore["srefresh"] = 1 + ignore["Replace"] = 1; ignore["Sreplace"] = 1 + ignore["Restart"] = 1; ignore["srestart"] = 1 + ignore["Resume"] = 1; ignore["Srsume"] = 1 + ignore["Suspend"] = 1; ignore["Ssuspend"] = 1 + ignore["Undo"] = 1; ignore["Sundo"] = 1 + ignore["Select"] = 1; ignore["Sselect"] = 1 + + # Rename some things for clarity. + rename["Ic"] = "Insert"; rename["Sic"] = "ShiftInsert" + rename["Dc"] = "Delete"; rename["Sdc"] = "ShiftDelete" + rename["Ppage"] = "PageUp" + rename["Npage"] = "PageDown" + rename["Btab"] = "BackTab" + rename["Shome"] = "ShiftHome" + rename["Send"] = "ShiftEnd" + rename["Sleft"] = "ShiftLeft" + rename["Sright"] = "ShiftRight" + } + + /^[^#]/ && $3 == "str" { + i++ + } + + $5 ~ /^KEY_/ { + name = toupper(substr($1, 5, 1)) substr($1, 6) + if (ignore[name] != "") + next + if (match(name, /^F([2-9][0-9]|1[3-9])/)) # Who has 64 function keys?! + next + if (rename[name] != "") + name = rename[name] + allkeys[name] = "" + + # TODO: should print: + # var Keys = map[Key]string{ + # F1: "\x1bOP", + # } + # printf "\t%s: \"%s\",\n", name, "TODO" + printf "\tcaps.TableStrs[%d]: %s,\n", i, name + } + + END { + print "}\n" + + print "// List of all key sequences we know about. This excludes most obscure ones not" + print "// present on modern devices." + print "const (" + print "// Special key used to signal errors." + print "UnknownSequence Key = iota + (1 << 32)\n" + for (k in allkeys) # TODO: weird order? + print k + print ")" + + print "// Names of named key constants." + print "var keyNames = map[Key]string{" + for (k in allkeys) + printf "\t%s: `%s`,\n", k, k + print "}\n" + } + EOF + )" +} + +main |
