...

Source file src/github.com/gdamore/tcell/v2/terminfo/mkinfo.go

Documentation: github.com/gdamore/tcell/v2/terminfo

     1  //go:build ignore
     2  // +build ignore
     3  
     4  // Copyright 2021 The TCell Authors
     5  //
     6  // Licensed under the Apache License, Version 2.0 (the "License");
     7  // you may not use file except in compliance with the License.
     8  // You may obtain a copy of the license at
     9  //
    10  //    http://www.apache.org/licenses/LICENSE-2.0
    11  //
    12  // Unless required by applicable law or agreed to in writing, software
    13  // distributed under the License is distributed on an "AS IS" BASIS,
    14  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    15  // See the License for the specific language governing permissions and
    16  // limitations under the License.
    17  
    18  // This command is used to generate suitable configuration files in either
    19  // go syntax or in JSON.  It defaults to JSON output on stdout.  If no
    20  // term values are specified on the command line, then $TERM is used.
    21  //
    22  // Usage is like this:
    23  //
    24  // mkinfo [-go file.go] [-quiet] [-nofatal] [-I <import>] [-P <pkg}] [<term>...]
    25  //
    26  // -go       specifies Go output into the named file.  Use - for stdout.
    27  // -nofatal  indicates that errors loading definitions should not be fatal
    28  // -P pkg    use the supplied package name
    29  // -I import use the named import instead of github.com/gdamore/tcell/v2/terminfo
    30  //
    31  
    32  package main
    33  
    34  import (
    35  	"bytes"
    36  	"errors"
    37  	"flag"
    38  	"fmt"
    39  	"io"
    40  	"os"
    41  	"os/exec"
    42  	"regexp"
    43  	"strconv"
    44  	"strings"
    45  
    46  	"github.com/gdamore/tcell/v2/terminfo"
    47  )
    48  
    49  type termcap struct {
    50  	name    string
    51  	desc    string
    52  	aliases []string
    53  	bools   map[string]bool
    54  	nums    map[string]int
    55  	strs    map[string]string
    56  }
    57  
    58  func (tc *termcap) getnum(s string) int {
    59  	return (tc.nums[s])
    60  }
    61  
    62  func (tc *termcap) getflag(s string) bool {
    63  	return (tc.bools[s])
    64  }
    65  
    66  func (tc *termcap) getstr(s string) string {
    67  	return (tc.strs[s])
    68  }
    69  
    70  const (
    71  	NONE = iota
    72  	CTRL
    73  	ESC
    74  )
    75  
    76  var notaddressable = errors.New("terminal not cursor addressable")
    77  
    78  func unescape(s string) string {
    79  	// Various escapes are in \x format.  Control codes are
    80  	// encoded as ^M (carat followed by ASCII equivalent).
    81  	// Escapes are: \e, \E - escape
    82  	//  \0 NULL, \n \l \r \t \b \f \s for equivalent C escape.
    83  	buf := &bytes.Buffer{}
    84  	esc := NONE
    85  
    86  	for i := 0; i < len(s); i++ {
    87  		c := s[i]
    88  		switch esc {
    89  		case NONE:
    90  			switch c {
    91  			case '\\':
    92  				esc = ESC
    93  			case '^':
    94  				esc = CTRL
    95  			default:
    96  				buf.WriteByte(c)
    97  			}
    98  		case CTRL:
    99  			buf.WriteByte(c ^ 1<<6)
   100  			esc = NONE
   101  		case ESC:
   102  			switch c {
   103  			case 'E', 'e':
   104  				buf.WriteByte(0x1b)
   105  			case '0', '1', '2', '3', '4', '5', '6', '7':
   106  				if i+2 < len(s) && s[i+1] >= '0' && s[i+1] <= '7' && s[i+2] >= '0' && s[i+2] <= '7' {
   107  					buf.WriteByte(((c - '0') * 64) + ((s[i+1] - '0') * 8) + (s[i+2] - '0'))
   108  					i = i + 2
   109  				} else if c == '0' {
   110  					buf.WriteByte(0)
   111  				}
   112  			case 'n':
   113  				buf.WriteByte('\n')
   114  			case 'r':
   115  				buf.WriteByte('\r')
   116  			case 't':
   117  				buf.WriteByte('\t')
   118  			case 'b':
   119  				buf.WriteByte('\b')
   120  			case 'f':
   121  				buf.WriteByte('\f')
   122  			case 's':
   123  				buf.WriteByte(' ')
   124  			case 'l':
   125  				panic("WTF: weird format: " + s)
   126  			default:
   127  				buf.WriteByte(c)
   128  			}
   129  			esc = NONE
   130  		}
   131  	}
   132  	return (buf.String())
   133  }
   134  
   135  func (tc *termcap) setupterm(name string) error {
   136  	cmd := exec.Command("infocmp", "-x", "-1", name)
   137  	output := &bytes.Buffer{}
   138  	cmd.Stdout = output
   139  
   140  	tc.strs = make(map[string]string)
   141  	tc.bools = make(map[string]bool)
   142  	tc.nums = make(map[string]int)
   143  
   144  	err := cmd.Run()
   145  	if err != nil {
   146  		return err
   147  	}
   148  
   149  	// Now parse the output.
   150  	// We get comment lines (starting with "#"), followed by
   151  	// a header line that looks like "<name>|<alias>|...|<desc>"
   152  	// then capabilities, one per line, starting with a tab and ending
   153  	// with a comma and newline.
   154  	lines := strings.Split(output.String(), "\n")
   155  	for len(lines) > 0 && strings.HasPrefix(lines[0], "#") {
   156  		lines = lines[1:]
   157  	}
   158  
   159  	// Ditch trailing empty last line
   160  	if lines[len(lines)-1] == "" {
   161  		lines = lines[:len(lines)-1]
   162  	}
   163  	header := lines[0]
   164  	if strings.HasSuffix(header, ",") {
   165  		header = header[:len(header)-1]
   166  	}
   167  	names := strings.Split(header, "|")
   168  	tc.name = names[0]
   169  	names = names[1:]
   170  	if len(names) > 0 {
   171  		tc.desc = names[len(names)-1]
   172  		names = names[:len(names)-1]
   173  	}
   174  	tc.aliases = names
   175  	for _, val := range lines[1:] {
   176  		if (!strings.HasPrefix(val, "\t")) ||
   177  			(!strings.HasSuffix(val, ",")) {
   178  			return (errors.New("malformed infocmp: " + val))
   179  		}
   180  
   181  		val = val[1:]
   182  		val = val[:len(val)-1]
   183  
   184  		if k := strings.SplitN(val, "=", 2); len(k) == 2 {
   185  			tc.strs[k[0]] = unescape(k[1])
   186  		} else if k := strings.SplitN(val, "#", 2); len(k) == 2 {
   187  			if u, err := strconv.ParseUint(k[1], 0, 0); err != nil {
   188  				return (err)
   189  			} else {
   190  				tc.nums[k[0]] = int(u)
   191  			}
   192  		} else {
   193  			tc.bools[val] = true
   194  		}
   195  	}
   196  	return nil
   197  }
   198  
   199  // This program is used to collect data from the system's terminfo library,
   200  // and write it into Go source code.  That is, we maintain our terminfo
   201  // capabilities encoded in the program.  It should never need to be run by
   202  // an end user, but developers can use this to add codes for additional
   203  // terminal types.
   204  func getinfo(name string) (*terminfo.Terminfo, string, error) {
   205  	var tc termcap
   206  	if err := tc.setupterm(name); err != nil {
   207  		if err != nil {
   208  			return nil, "", err
   209  		}
   210  	}
   211  	t := &terminfo.Terminfo{}
   212  	// If this is an alias record, then just emit the alias
   213  	t.Name = tc.name
   214  	if t.Name != name {
   215  		return t, "", nil
   216  	}
   217  	t.Aliases = tc.aliases
   218  	t.Colors = tc.getnum("colors")
   219  	t.Columns = tc.getnum("cols")
   220  	t.Lines = tc.getnum("lines")
   221  	t.Bell = tc.getstr("bel")
   222  	t.Clear = tc.getstr("clear")
   223  	t.EnterCA = tc.getstr("smcup")
   224  	t.ExitCA = tc.getstr("rmcup")
   225  	t.ShowCursor = tc.getstr("cnorm")
   226  	t.HideCursor = tc.getstr("civis")
   227  	t.AttrOff = tc.getstr("sgr0")
   228  	t.Underline = tc.getstr("smul")
   229  	t.Bold = tc.getstr("bold")
   230  	t.Blink = tc.getstr("blink")
   231  	t.Dim = tc.getstr("dim")
   232  	t.Italic = tc.getstr("sitm")
   233  	t.Reverse = tc.getstr("rev")
   234  	t.EnterKeypad = tc.getstr("smkx")
   235  	t.ExitKeypad = tc.getstr("rmkx")
   236  	t.SetFg = tc.getstr("setaf")
   237  	t.SetBg = tc.getstr("setab")
   238  	t.ResetFgBg = tc.getstr("op")
   239  	t.SetCursor = tc.getstr("cup")
   240  	t.CursorBack1 = tc.getstr("cub1")
   241  	t.CursorUp1 = tc.getstr("cuu1")
   242  	t.InsertChar = tc.getstr("ich1")
   243  	t.AutoMargin = tc.getflag("am")
   244  	t.KeyF1 = tc.getstr("kf1")
   245  	t.KeyF2 = tc.getstr("kf2")
   246  	t.KeyF3 = tc.getstr("kf3")
   247  	t.KeyF4 = tc.getstr("kf4")
   248  	t.KeyF5 = tc.getstr("kf5")
   249  	t.KeyF6 = tc.getstr("kf6")
   250  	t.KeyF7 = tc.getstr("kf7")
   251  	t.KeyF8 = tc.getstr("kf8")
   252  	t.KeyF9 = tc.getstr("kf9")
   253  	t.KeyF10 = tc.getstr("kf10")
   254  	t.KeyF11 = tc.getstr("kf11")
   255  	t.KeyF12 = tc.getstr("kf12")
   256  	t.KeyInsert = tc.getstr("kich1")
   257  	t.KeyDelete = tc.getstr("kdch1")
   258  	t.KeyBackspace = tc.getstr("kbs")
   259  	t.KeyHome = tc.getstr("khome")
   260  	t.KeyEnd = tc.getstr("kend")
   261  	t.KeyUp = tc.getstr("kcuu1")
   262  	t.KeyDown = tc.getstr("kcud1")
   263  	t.KeyRight = tc.getstr("kcuf1")
   264  	t.KeyLeft = tc.getstr("kcub1")
   265  	t.KeyPgDn = tc.getstr("knp")
   266  	t.KeyPgUp = tc.getstr("kpp")
   267  	t.KeyBacktab = tc.getstr("kcbt")
   268  	t.KeyExit = tc.getstr("kext")
   269  	t.KeyCancel = tc.getstr("kcan")
   270  	t.KeyPrint = tc.getstr("kprt")
   271  	t.KeyHelp = tc.getstr("khlp")
   272  	t.KeyClear = tc.getstr("kclr")
   273  	t.AltChars = tc.getstr("acsc")
   274  	t.EnterAcs = tc.getstr("smacs")
   275  	t.ExitAcs = tc.getstr("rmacs")
   276  	t.EnableAcs = tc.getstr("enacs")
   277  	t.StrikeThrough = tc.getstr("smxx")
   278  	t.Mouse = tc.getstr("kmous")
   279  
   280  	t.Modifiers = terminfo.ModifiersNone
   281  
   282  	// Terminfo lacks descriptions for a bunch of modified keys,
   283  	// but modern XTerm and emulators often have them. We detect
   284  	// this based on compatible definitions for shifted right.
   285  	// We also choose to use our modifiers for function keys --
   286  	// the terminfo entries list these all as higher coded escape
   287  	// keys, but it's nicer to match them to modifiers.
   288  	if tc.getstr("kRIT") == "\x1b[1;2C" {
   289  		t.Modifiers = terminfo.ModifiersXTerm
   290  	} else {
   291  		// Lookup high level function keys.
   292  		t.KeyShfInsert = tc.getstr("kIC")
   293  		t.KeyShfDelete = tc.getstr("kDC")
   294  		t.KeyShfRight = tc.getstr("kRIT")
   295  		t.KeyShfLeft = tc.getstr("kLFT")
   296  		t.KeyShfHome = tc.getstr("kHOM")
   297  		t.KeyShfEnd = tc.getstr("kEND")
   298  		t.KeyF13 = tc.getstr("kf13")
   299  		t.KeyF14 = tc.getstr("kf14")
   300  		t.KeyF15 = tc.getstr("kf15")
   301  		t.KeyF16 = tc.getstr("kf16")
   302  		t.KeyF17 = tc.getstr("kf17")
   303  		t.KeyF18 = tc.getstr("kf18")
   304  		t.KeyF19 = tc.getstr("kf19")
   305  		t.KeyF20 = tc.getstr("kf20")
   306  		t.KeyF21 = tc.getstr("kf21")
   307  		t.KeyF22 = tc.getstr("kf22")
   308  		t.KeyF23 = tc.getstr("kf23")
   309  		t.KeyF24 = tc.getstr("kf24")
   310  		t.KeyF25 = tc.getstr("kf25")
   311  		t.KeyF26 = tc.getstr("kf26")
   312  		t.KeyF27 = tc.getstr("kf27")
   313  		t.KeyF28 = tc.getstr("kf28")
   314  		t.KeyF29 = tc.getstr("kf29")
   315  		t.KeyF30 = tc.getstr("kf30")
   316  		t.KeyF31 = tc.getstr("kf31")
   317  		t.KeyF32 = tc.getstr("kf32")
   318  		t.KeyF33 = tc.getstr("kf33")
   319  		t.KeyF34 = tc.getstr("kf34")
   320  		t.KeyF35 = tc.getstr("kf35")
   321  		t.KeyF36 = tc.getstr("kf36")
   322  		t.KeyF37 = tc.getstr("kf37")
   323  		t.KeyF38 = tc.getstr("kf38")
   324  		t.KeyF39 = tc.getstr("kf39")
   325  		t.KeyF40 = tc.getstr("kf40")
   326  		t.KeyF41 = tc.getstr("kf41")
   327  		t.KeyF42 = tc.getstr("kf42")
   328  		t.KeyF43 = tc.getstr("kf43")
   329  		t.KeyF44 = tc.getstr("kf44")
   330  		t.KeyF45 = tc.getstr("kf45")
   331  		t.KeyF46 = tc.getstr("kf46")
   332  		t.KeyF47 = tc.getstr("kf47")
   333  		t.KeyF48 = tc.getstr("kf48")
   334  		t.KeyF49 = tc.getstr("kf49")
   335  		t.KeyF50 = tc.getstr("kf50")
   336  		t.KeyF51 = tc.getstr("kf51")
   337  		t.KeyF52 = tc.getstr("kf52")
   338  		t.KeyF53 = tc.getstr("kf53")
   339  		t.KeyF54 = tc.getstr("kf54")
   340  		t.KeyF55 = tc.getstr("kf55")
   341  		t.KeyF56 = tc.getstr("kf56")
   342  		t.KeyF57 = tc.getstr("kf57")
   343  		t.KeyF58 = tc.getstr("kf58")
   344  		t.KeyF59 = tc.getstr("kf59")
   345  		t.KeyF60 = tc.getstr("kf60")
   346  		t.KeyF61 = tc.getstr("kf61")
   347  		t.KeyF62 = tc.getstr("kf62")
   348  		t.KeyF63 = tc.getstr("kf63")
   349  		t.KeyF64 = tc.getstr("kf64")
   350  	}
   351  
   352  	// And the same thing for rxvt.
   353  	// It seems that urxvt at least send ESC as ALT prefix for these,
   354  	// although some places seem to indicate a separate ALT key sequence.
   355  	// Users are encouraged to update to an emulator that more closely
   356  	// matches xterm for better functionality.
   357  	if t.KeyShfRight == "\x1b[c" && t.KeyShfLeft == "\x1b[d" {
   358  		t.KeyShfUp = "\x1b[a"
   359  		t.KeyShfDown = "\x1b[b"
   360  		t.KeyCtrlUp = "\x1b[Oa"
   361  		t.KeyCtrlDown = "\x1b[Ob"
   362  		t.KeyCtrlRight = "\x1b[Oc"
   363  		t.KeyCtrlLeft = "\x1b[Od"
   364  	}
   365  	if t.KeyShfHome == "\x1b[7$" && t.KeyShfEnd == "\x1b[8$" {
   366  		t.KeyCtrlHome = "\x1b[7^"
   367  		t.KeyCtrlEnd = "\x1b[8^"
   368  	}
   369  
   370  	// Technically the RGB flag that is provided for xterm-direct is not
   371  	// quite right.  The problem is that the -direct flag that was introduced
   372  	// with ncurses 6.1 requires a parsing for the parameters that we lack.
   373  	// For this case we'll just assume it's XTerm compatible.  Someday this
   374  	// may be incorrect, but right now it is correct, and nobody uses it
   375  	// anyway.
   376  	if tc.getflag("Tc") {
   377  		// This presumes XTerm 24-bit true color.
   378  		t.TrueColor = true
   379  	} else if tc.getflag("RGB") {
   380  		// This is for xterm-direct, which uses a different scheme entirely.
   381  		// (ncurses went a very different direction from everyone else, and
   382  		// so it's unlikely anything is using this definition.)
   383  		t.TrueColor = true
   384  		t.SetBg = "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m"
   385  		t.SetFg = "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m"
   386  	}
   387  
   388  	// We only support colors in ANSI 8 or 256 color mode.
   389  	if t.Colors < 8 || t.SetFg == "" {
   390  		t.Colors = 0
   391  	}
   392  	if t.SetCursor == "" {
   393  		return nil, "", notaddressable
   394  	}
   395  
   396  	// For padding, we lookup the pad char.  If that isn't present,
   397  	// and npc is *not* set, then we assume a null byte.
   398  	t.PadChar = tc.getstr("pad")
   399  	if t.PadChar == "" {
   400  		if !tc.getflag("npc") {
   401  			t.PadChar = "\u0000"
   402  		}
   403  	}
   404  
   405  	// For terminals that use "standard" SGR sequences, lets combine the
   406  	// foreground and background together.
   407  	if strings.HasPrefix(t.SetFg, "\x1b[") &&
   408  		strings.HasPrefix(t.SetBg, "\x1b[") &&
   409  		strings.HasSuffix(t.SetFg, "m") &&
   410  		strings.HasSuffix(t.SetBg, "m") {
   411  		fg := t.SetFg[:len(t.SetFg)-1]
   412  		r := regexp.MustCompile("%p1")
   413  		bg := r.ReplaceAllString(t.SetBg[2:], "%p2")
   414  		t.SetFgBg = fg + ";" + bg
   415  	}
   416  
   417  	return t, tc.desc, nil
   418  }
   419  
   420  func dotGoAddInt(w io.Writer, n string, i int) {
   421  	if i == 0 {
   422  		// initialized to 0, ignore
   423  		return
   424  	}
   425  	fmt.Fprintf(w, "\t\t%-13s %d,\n", n+":", i)
   426  }
   427  func dotGoAddStr(w io.Writer, n string, s string) {
   428  	if s == "" {
   429  		return
   430  	}
   431  	fmt.Fprintf(w, "\t\t%-13s %q,\n", n+":", s)
   432  }
   433  func dotGoAddFlag(w io.Writer, n string, b bool) {
   434  	if !b {
   435  		// initialized to 0, ignore
   436  		return
   437  	}
   438  	fmt.Fprintf(w, "\t\t%-13s true,\n", n+":")
   439  }
   440  
   441  func dotGoAddArr(w io.Writer, n string, a []string) {
   442  	if len(a) == 0 {
   443  		return
   444  	}
   445  	fmt.Fprintf(w, "\t\t%-13s []string{", n+":")
   446  	did := false
   447  	for _, b := range a {
   448  		if did {
   449  			fmt.Fprint(w, ", ")
   450  		}
   451  		did = true
   452  		fmt.Fprintf(w, "%q", b)
   453  	}
   454  	fmt.Fprintln(w, "},")
   455  }
   456  
   457  func dotGoHeader(w io.Writer, packname, tipackname string) {
   458  	fmt.Fprintln(w, "// Generated automatically.  DO NOT HAND-EDIT.")
   459  	fmt.Fprintln(w, "")
   460  	fmt.Fprintf(w, "package %s\n", packname)
   461  	fmt.Fprintln(w, "")
   462  	fmt.Fprintf(w, "import \"%s\"\n", tipackname)
   463  	fmt.Fprintln(w, "")
   464  }
   465  
   466  func dotGoTrailer(w io.Writer) {
   467  }
   468  
   469  func dotGoInfo(w io.Writer, terms []*TData) {
   470  
   471  	fmt.Fprintln(w, "func init() {")
   472  	for _, t := range terms {
   473  		fmt.Fprintf(w, "\n\t// %s\n", t.Desc)
   474  		fmt.Fprintln(w, "\tterminfo.AddTerminfo(&terminfo.Terminfo{")
   475  		dotGoAddStr(w, "Name", t.Name)
   476  		dotGoAddArr(w, "Aliases", t.Aliases)
   477  		dotGoAddInt(w, "Columns", t.Columns)
   478  		dotGoAddInt(w, "Lines", t.Lines)
   479  		dotGoAddInt(w, "Colors", t.Colors)
   480  		dotGoAddStr(w, "Bell", t.Bell)
   481  		dotGoAddStr(w, "Clear", t.Clear)
   482  		dotGoAddStr(w, "EnterCA", t.EnterCA)
   483  		dotGoAddStr(w, "ExitCA", t.ExitCA)
   484  		dotGoAddStr(w, "ShowCursor", t.ShowCursor)
   485  		dotGoAddStr(w, "HideCursor", t.HideCursor)
   486  		dotGoAddStr(w, "AttrOff", t.AttrOff)
   487  		dotGoAddStr(w, "Underline", t.Underline)
   488  		dotGoAddStr(w, "Bold", t.Bold)
   489  		dotGoAddStr(w, "Dim", t.Dim)
   490  		dotGoAddStr(w, "Italic", t.Italic)
   491  		dotGoAddStr(w, "Blink", t.Blink)
   492  		dotGoAddStr(w, "Reverse", t.Reverse)
   493  		dotGoAddStr(w, "EnterKeypad", t.EnterKeypad)
   494  		dotGoAddStr(w, "ExitKeypad", t.ExitKeypad)
   495  		dotGoAddStr(w, "SetFg", t.SetFg)
   496  		dotGoAddStr(w, "SetBg", t.SetBg)
   497  		dotGoAddStr(w, "SetFgBg", t.SetFgBg)
   498  		dotGoAddStr(w, "ResetFgBg", t.ResetFgBg)
   499  		dotGoAddStr(w, "PadChar", t.PadChar)
   500  		dotGoAddStr(w, "AltChars", t.AltChars)
   501  		dotGoAddStr(w, "EnterAcs", t.EnterAcs)
   502  		dotGoAddStr(w, "ExitAcs", t.ExitAcs)
   503  		dotGoAddStr(w, "EnableAcs", t.EnableAcs)
   504  		dotGoAddStr(w, "SetFgRGB", t.SetFgRGB)
   505  		dotGoAddStr(w, "SetBgRGB", t.SetBgRGB)
   506  		dotGoAddStr(w, "SetFgBgRGB", t.SetFgBgRGB)
   507  		dotGoAddStr(w, "StrikeThrough", t.StrikeThrough)
   508  		dotGoAddStr(w, "Mouse", t.Mouse)
   509  		dotGoAddStr(w, "SetCursor", t.SetCursor)
   510  		dotGoAddStr(w, "CursorBack1", t.CursorBack1)
   511  		dotGoAddStr(w, "CursorUp1", t.CursorUp1)
   512  		dotGoAddStr(w, "KeyUp", t.KeyUp)
   513  		dotGoAddStr(w, "KeyDown", t.KeyDown)
   514  		dotGoAddStr(w, "KeyRight", t.KeyRight)
   515  		dotGoAddStr(w, "KeyLeft", t.KeyLeft)
   516  		dotGoAddStr(w, "KeyInsert", t.KeyInsert)
   517  		dotGoAddStr(w, "KeyDelete", t.KeyDelete)
   518  		dotGoAddStr(w, "KeyBackspace", t.KeyBackspace)
   519  		dotGoAddStr(w, "KeyHome", t.KeyHome)
   520  		dotGoAddStr(w, "KeyEnd", t.KeyEnd)
   521  		dotGoAddStr(w, "KeyPgUp", t.KeyPgUp)
   522  		dotGoAddStr(w, "KeyPgDn", t.KeyPgDn)
   523  		dotGoAddStr(w, "KeyF1", t.KeyF1)
   524  		dotGoAddStr(w, "KeyF2", t.KeyF2)
   525  		dotGoAddStr(w, "KeyF3", t.KeyF3)
   526  		dotGoAddStr(w, "KeyF4", t.KeyF4)
   527  		dotGoAddStr(w, "KeyF5", t.KeyF5)
   528  		dotGoAddStr(w, "KeyF6", t.KeyF6)
   529  		dotGoAddStr(w, "KeyF7", t.KeyF7)
   530  		dotGoAddStr(w, "KeyF8", t.KeyF8)
   531  		dotGoAddStr(w, "KeyF9", t.KeyF9)
   532  		dotGoAddStr(w, "KeyF10", t.KeyF10)
   533  		dotGoAddStr(w, "KeyF11", t.KeyF11)
   534  		dotGoAddStr(w, "KeyF12", t.KeyF12)
   535  		// Extended keys.  We don't report these if they are going to be
   536  		// handled as if they were XTerm sequences.
   537  		dotGoAddStr(w, "KeyF13", t.KeyF13)
   538  		dotGoAddStr(w, "KeyF14", t.KeyF14)
   539  		dotGoAddStr(w, "KeyF15", t.KeyF15)
   540  		dotGoAddStr(w, "KeyF16", t.KeyF16)
   541  		dotGoAddStr(w, "KeyF17", t.KeyF17)
   542  		dotGoAddStr(w, "KeyF18", t.KeyF18)
   543  		dotGoAddStr(w, "KeyF19", t.KeyF19)
   544  		dotGoAddStr(w, "KeyF20", t.KeyF20)
   545  		dotGoAddStr(w, "KeyF21", t.KeyF21)
   546  		dotGoAddStr(w, "KeyF22", t.KeyF22)
   547  		dotGoAddStr(w, "KeyF23", t.KeyF23)
   548  		dotGoAddStr(w, "KeyF24", t.KeyF24)
   549  		dotGoAddStr(w, "KeyF25", t.KeyF25)
   550  		dotGoAddStr(w, "KeyF26", t.KeyF26)
   551  		dotGoAddStr(w, "KeyF27", t.KeyF27)
   552  		dotGoAddStr(w, "KeyF28", t.KeyF28)
   553  		dotGoAddStr(w, "KeyF29", t.KeyF29)
   554  		dotGoAddStr(w, "KeyF30", t.KeyF30)
   555  		dotGoAddStr(w, "KeyF31", t.KeyF31)
   556  		dotGoAddStr(w, "KeyF32", t.KeyF32)
   557  		dotGoAddStr(w, "KeyF33", t.KeyF33)
   558  		dotGoAddStr(w, "KeyF34", t.KeyF34)
   559  		dotGoAddStr(w, "KeyF35", t.KeyF35)
   560  		dotGoAddStr(w, "KeyF36", t.KeyF36)
   561  		dotGoAddStr(w, "KeyF37", t.KeyF37)
   562  		dotGoAddStr(w, "KeyF38", t.KeyF38)
   563  		dotGoAddStr(w, "KeyF39", t.KeyF39)
   564  		dotGoAddStr(w, "KeyF40", t.KeyF40)
   565  		dotGoAddStr(w, "KeyF41", t.KeyF41)
   566  		dotGoAddStr(w, "KeyF42", t.KeyF42)
   567  		dotGoAddStr(w, "KeyF43", t.KeyF43)
   568  		dotGoAddStr(w, "KeyF44", t.KeyF44)
   569  		dotGoAddStr(w, "KeyF45", t.KeyF45)
   570  		dotGoAddStr(w, "KeyF46", t.KeyF46)
   571  		dotGoAddStr(w, "KeyF47", t.KeyF47)
   572  		dotGoAddStr(w, "KeyF48", t.KeyF48)
   573  		dotGoAddStr(w, "KeyF49", t.KeyF49)
   574  		dotGoAddStr(w, "KeyF50", t.KeyF50)
   575  		dotGoAddStr(w, "KeyF51", t.KeyF51)
   576  		dotGoAddStr(w, "KeyF52", t.KeyF52)
   577  		dotGoAddStr(w, "KeyF53", t.KeyF53)
   578  		dotGoAddStr(w, "KeyF54", t.KeyF54)
   579  		dotGoAddStr(w, "KeyF55", t.KeyF55)
   580  		dotGoAddStr(w, "KeyF56", t.KeyF56)
   581  		dotGoAddStr(w, "KeyF57", t.KeyF57)
   582  		dotGoAddStr(w, "KeyF58", t.KeyF58)
   583  		dotGoAddStr(w, "KeyF59", t.KeyF59)
   584  		dotGoAddStr(w, "KeyF60", t.KeyF60)
   585  		dotGoAddStr(w, "KeyF61", t.KeyF61)
   586  		dotGoAddStr(w, "KeyF62", t.KeyF62)
   587  		dotGoAddStr(w, "KeyF63", t.KeyF63)
   588  		dotGoAddStr(w, "KeyF64", t.KeyF64)
   589  		dotGoAddStr(w, "KeyCancel", t.KeyCancel)
   590  		dotGoAddStr(w, "KeyPrint", t.KeyPrint)
   591  		dotGoAddStr(w, "KeyExit", t.KeyExit)
   592  		dotGoAddStr(w, "KeyHelp", t.KeyHelp)
   593  		dotGoAddStr(w, "KeyClear", t.KeyClear)
   594  		dotGoAddStr(w, "KeyBacktab", t.KeyBacktab)
   595  		dotGoAddStr(w, "KeyShfLeft", t.KeyShfLeft)
   596  		dotGoAddStr(w, "KeyShfRight", t.KeyShfRight)
   597  		dotGoAddStr(w, "KeyShfUp", t.KeyShfUp)
   598  		dotGoAddStr(w, "KeyShfDown", t.KeyShfDown)
   599  		dotGoAddStr(w, "KeyShfHome", t.KeyShfHome)
   600  		dotGoAddStr(w, "KeyShfEnd", t.KeyShfEnd)
   601  		dotGoAddStr(w, "KeyShfInsert", t.KeyShfInsert)
   602  		dotGoAddStr(w, "KeyShfDelete", t.KeyShfDelete)
   603  		dotGoAddStr(w, "KeyCtrlUp", t.KeyCtrlUp)
   604  		dotGoAddStr(w, "KeyCtrlDown", t.KeyCtrlDown)
   605  		dotGoAddStr(w, "KeyCtrlRight", t.KeyCtrlRight)
   606  		dotGoAddStr(w, "KeyCtrlLeft", t.KeyCtrlLeft)
   607  		dotGoAddStr(w, "KeyCtrlHome", t.KeyCtrlHome)
   608  		dotGoAddStr(w, "KeyCtrlEnd", t.KeyCtrlEnd)
   609  		dotGoAddInt(w, "Modifiers", t.Modifiers)
   610  		dotGoAddFlag(w, "TrueColor", t.TrueColor)
   611  		dotGoAddFlag(w, "AutoMargin", t.AutoMargin)
   612  		dotGoAddStr(w, "InsertChar", t.InsertChar)
   613  		dotGoAddStr(w, "CursorDefault", t.CursorDefault)
   614  		dotGoAddStr(w, "CursorBlinkingBlock", t.CursorBlinkingBlock)
   615  		dotGoAddStr(w, "CursorSteadyBlock", t.CursorSteadyBlock)
   616  		dotGoAddStr(w, "CursorBlinkingUnderline", t.CursorBlinkingUnderline)
   617  		dotGoAddStr(w, "CursorSteadyUnderline", t.CursorSteadyUnderline)
   618  		dotGoAddStr(w, "CursorBlinkingBar", t.CursorBlinkingBar)
   619  		dotGoAddStr(w, "CursorSteadyBar", t.CursorSteadyBar)
   620  		fmt.Fprintln(w, "\t})")
   621  	}
   622  	fmt.Fprintln(w, "}")
   623  }
   624  
   625  var packname = ""
   626  var tipackname = "github.com/gdamore/tcell/v2/terminfo"
   627  
   628  func dotGoFile(fname string, terms []*TData) error {
   629  	w := os.Stdout
   630  	var e error
   631  	if fname != "-" && fname != "" {
   632  		if w, e = os.Create(fname); e != nil {
   633  			return e
   634  		}
   635  	}
   636  	if packname == "" {
   637  		packname = strings.Replace(terms[0].Name, "-", "_", -1)
   638  	}
   639  	dotGoHeader(w, packname, tipackname)
   640  	dotGoInfo(w, terms)
   641  	dotGoTrailer(w)
   642  	if w != os.Stdout {
   643  		w.Close()
   644  	}
   645  	cmd := exec.Command("go", "fmt", fname)
   646  	cmd.Run()
   647  	return nil
   648  }
   649  
   650  type TData struct {
   651  	Desc string
   652  
   653  	terminfo.Terminfo
   654  }
   655  
   656  func main() {
   657  	gofile := ""
   658  	nofatal := false
   659  	quiet := false
   660  	all := false
   661  
   662  	flag.StringVar(&gofile, "go", "", "generate go source in named file")
   663  	flag.StringVar(&tipackname, "I", tipackname, "import package path")
   664  	flag.StringVar(&packname, "P", packname, "package name (go source)")
   665  	flag.BoolVar(&nofatal, "nofatal", false, "errors are not fatal")
   666  	flag.BoolVar(&quiet, "quiet", false, "suppress error messages")
   667  	flag.BoolVar(&all, "all", false, "load all terminals from terminfo")
   668  	flag.Parse()
   669  	var e error
   670  
   671  	args := flag.Args()
   672  	if len(args) == 0 {
   673  		args = []string{os.Getenv("TERM")}
   674  	}
   675  
   676  	tdata := make([]*TData, 0)
   677  
   678  	for _, term := range args {
   679  		if t, desc, e := getinfo(term); e != nil {
   680  			if all && e == notaddressable {
   681  				continue
   682  			}
   683  			if !quiet {
   684  				fmt.Fprintf(os.Stderr,
   685  					"Failed loading %s: %v\n", term, e)
   686  			}
   687  			if !nofatal {
   688  				os.Exit(1)
   689  			}
   690  		} else {
   691  			tdata = append(tdata, &TData{
   692  				Desc:     desc,
   693  				Terminfo: *t,
   694  			})
   695  		}
   696  	}
   697  
   698  	if len(tdata) == 0 {
   699  		// No data.
   700  		os.Exit(0)
   701  	}
   702  
   703  	e = dotGoFile(gofile, tdata)
   704  	if e != nil {
   705  		fmt.Fprintf(os.Stderr, "Failed %s: %v", gofile, e)
   706  		os.Exit(1)
   707  	}
   708  }
   709  

View as plain text