summaryrefslogtreecommitdiff
path: root/vendor/github.com/ijc/Gotty
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/ijc/Gotty')
-rw-r--r--vendor/github.com/ijc/Gotty/LICENSE26
-rw-r--r--vendor/github.com/ijc/Gotty/README5
-rw-r--r--vendor/github.com/ijc/Gotty/TODO3
-rw-r--r--vendor/github.com/ijc/Gotty/attributes.go514
-rw-r--r--vendor/github.com/ijc/Gotty/gotty.go244
-rw-r--r--vendor/github.com/ijc/Gotty/parser.go362
-rw-r--r--vendor/github.com/ijc/Gotty/types.go23
7 files changed, 1177 insertions, 0 deletions
diff --git a/vendor/github.com/ijc/Gotty/LICENSE b/vendor/github.com/ijc/Gotty/LICENSE
new file mode 100644
index 000000000..0b71c9736
--- /dev/null
+++ b/vendor/github.com/ijc/Gotty/LICENSE
@@ -0,0 +1,26 @@
+Copyright (c) 2012, Neal van Veen (nealvanveen@gmail.com)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+The views and conclusions contained in the software and documentation are those
+of the authors and should not be interpreted as representing official policies,
+either expressed or implied, of the FreeBSD Project.
diff --git a/vendor/github.com/ijc/Gotty/README b/vendor/github.com/ijc/Gotty/README
new file mode 100644
index 000000000..a6b0d9a8f
--- /dev/null
+++ b/vendor/github.com/ijc/Gotty/README
@@ -0,0 +1,5 @@
+Gotty is a library written in Go that determines and reads termcap database
+files to produce an interface for interacting with the capabilities of a
+terminal.
+See the godoc documentation or the source code for more information about
+function usage.
diff --git a/vendor/github.com/ijc/Gotty/TODO b/vendor/github.com/ijc/Gotty/TODO
new file mode 100644
index 000000000..470460531
--- /dev/null
+++ b/vendor/github.com/ijc/Gotty/TODO
@@ -0,0 +1,3 @@
+gotty.go:// TODO add more concurrency to name lookup, look for more opportunities.
+all:// TODO add more documentation, with function usage in a doc.go file.
+all:// TODO add more testing/benchmarking with go test.
diff --git a/vendor/github.com/ijc/Gotty/attributes.go b/vendor/github.com/ijc/Gotty/attributes.go
new file mode 100644
index 000000000..a4c005fae
--- /dev/null
+++ b/vendor/github.com/ijc/Gotty/attributes.go
@@ -0,0 +1,514 @@
+// Copyright 2012 Neal van Veen. All rights reserved.
+// Usage of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package gotty
+
+// Boolean capabilities
+var BoolAttr = [...]string{
+ "auto_left_margin", "bw",
+ "auto_right_margin", "am",
+ "no_esc_ctlc", "xsb",
+ "ceol_standout_glitch", "xhp",
+ "eat_newline_glitch", "xenl",
+ "erase_overstrike", "eo",
+ "generic_type", "gn",
+ "hard_copy", "hc",
+ "has_meta_key", "km",
+ "has_status_line", "hs",
+ "insert_null_glitch", "in",
+ "memory_above", "da",
+ "memory_below", "db",
+ "move_insert_mode", "mir",
+ "move_standout_mode", "msgr",
+ "over_strike", "os",
+ "status_line_esc_ok", "eslok",
+ "dest_tabs_magic_smso", "xt",
+ "tilde_glitch", "hz",
+ "transparent_underline", "ul",
+ "xon_xoff", "nxon",
+ "needs_xon_xoff", "nxon",
+ "prtr_silent", "mc5i",
+ "hard_cursor", "chts",
+ "non_rev_rmcup", "nrrmc",
+ "no_pad_char", "npc",
+ "non_dest_scroll_region", "ndscr",
+ "can_change", "ccc",
+ "back_color_erase", "bce",
+ "hue_lightness_saturation", "hls",
+ "col_addr_glitch", "xhpa",
+ "cr_cancels_micro_mode", "crxm",
+ "has_print_wheel", "daisy",
+ "row_addr_glitch", "xvpa",
+ "semi_auto_right_margin", "sam",
+ "cpi_changes_res", "cpix",
+ "lpi_changes_res", "lpix",
+ "backspaces_with_bs", "",
+ "crt_no_scrolling", "",
+ "no_correctly_working_cr", "",
+ "gnu_has_meta_key", "",
+ "linefeed_is_newline", "",
+ "has_hardware_tabs", "",
+ "return_does_clr_eol", "",
+}
+
+// Numerical capabilities
+var NumAttr = [...]string{
+ "columns", "cols",
+ "init_tabs", "it",
+ "lines", "lines",
+ "lines_of_memory", "lm",
+ "magic_cookie_glitch", "xmc",
+ "padding_baud_rate", "pb",
+ "virtual_terminal", "vt",
+ "width_status_line", "wsl",
+ "num_labels", "nlab",
+ "label_height", "lh",
+ "label_width", "lw",
+ "max_attributes", "ma",
+ "maximum_windows", "wnum",
+ "max_colors", "colors",
+ "max_pairs", "pairs",
+ "no_color_video", "ncv",
+ "buffer_capacity", "bufsz",
+ "dot_vert_spacing", "spinv",
+ "dot_horz_spacing", "spinh",
+ "max_micro_address", "maddr",
+ "max_micro_jump", "mjump",
+ "micro_col_size", "mcs",
+ "micro_line_size", "mls",
+ "number_of_pins", "npins",
+ "output_res_char", "orc",
+ "output_res_line", "orl",
+ "output_res_horz_inch", "orhi",
+ "output_res_vert_inch", "orvi",
+ "print_rate", "cps",
+ "wide_char_size", "widcs",
+ "buttons", "btns",
+ "bit_image_entwining", "bitwin",
+ "bit_image_type", "bitype",
+ "magic_cookie_glitch_ul", "",
+ "carriage_return_delay", "",
+ "new_line_delay", "",
+ "backspace_delay", "",
+ "horizontal_tab_delay", "",
+ "number_of_function_keys", "",
+}
+
+// String capabilities
+var StrAttr = [...]string{
+ "back_tab", "cbt",
+ "bell", "bel",
+ "carriage_return", "cr",
+ "change_scroll_region", "csr",
+ "clear_all_tabs", "tbc",
+ "clear_screen", "clear",
+ "clr_eol", "el",
+ "clr_eos", "ed",
+ "column_address", "hpa",
+ "command_character", "cmdch",
+ "cursor_address", "cup",
+ "cursor_down", "cud1",
+ "cursor_home", "home",
+ "cursor_invisible", "civis",
+ "cursor_left", "cub1",
+ "cursor_mem_address", "mrcup",
+ "cursor_normal", "cnorm",
+ "cursor_right", "cuf1",
+ "cursor_to_ll", "ll",
+ "cursor_up", "cuu1",
+ "cursor_visible", "cvvis",
+ "delete_character", "dch1",
+ "delete_line", "dl1",
+ "dis_status_line", "dsl",
+ "down_half_line", "hd",
+ "enter_alt_charset_mode", "smacs",
+ "enter_blink_mode", "blink",
+ "enter_bold_mode", "bold",
+ "enter_ca_mode", "smcup",
+ "enter_delete_mode", "smdc",
+ "enter_dim_mode", "dim",
+ "enter_insert_mode", "smir",
+ "enter_secure_mode", "invis",
+ "enter_protected_mode", "prot",
+ "enter_reverse_mode", "rev",
+ "enter_standout_mode", "smso",
+ "enter_underline_mode", "smul",
+ "erase_chars", "ech",
+ "exit_alt_charset_mode", "rmacs",
+ "exit_attribute_mode", "sgr0",
+ "exit_ca_mode", "rmcup",
+ "exit_delete_mode", "rmdc",
+ "exit_insert_mode", "rmir",
+ "exit_standout_mode", "rmso",
+ "exit_underline_mode", "rmul",
+ "flash_screen", "flash",
+ "form_feed", "ff",
+ "from_status_line", "fsl",
+ "init_1string", "is1",
+ "init_2string", "is2",
+ "init_3string", "is3",
+ "init_file", "if",
+ "insert_character", "ich1",
+ "insert_line", "il1",
+ "insert_padding", "ip",
+ "key_backspace", "kbs",
+ "key_catab", "ktbc",
+ "key_clear", "kclr",
+ "key_ctab", "kctab",
+ "key_dc", "kdch1",
+ "key_dl", "kdl1",
+ "key_down", "kcud1",
+ "key_eic", "krmir",
+ "key_eol", "kel",
+ "key_eos", "ked",
+ "key_f0", "kf0",
+ "key_f1", "kf1",
+ "key_f10", "kf10",
+ "key_f2", "kf2",
+ "key_f3", "kf3",
+ "key_f4", "kf4",
+ "key_f5", "kf5",
+ "key_f6", "kf6",
+ "key_f7", "kf7",
+ "key_f8", "kf8",
+ "key_f9", "kf9",
+ "key_home", "khome",
+ "key_ic", "kich1",
+ "key_il", "kil1",
+ "key_left", "kcub1",
+ "key_ll", "kll",
+ "key_npage", "knp",
+ "key_ppage", "kpp",
+ "key_right", "kcuf1",
+ "key_sf", "kind",
+ "key_sr", "kri",
+ "key_stab", "khts",
+ "key_up", "kcuu1",
+ "keypad_local", "rmkx",
+ "keypad_xmit", "smkx",
+ "lab_f0", "lf0",
+ "lab_f1", "lf1",
+ "lab_f10", "lf10",
+ "lab_f2", "lf2",
+ "lab_f3", "lf3",
+ "lab_f4", "lf4",
+ "lab_f5", "lf5",
+ "lab_f6", "lf6",
+ "lab_f7", "lf7",
+ "lab_f8", "lf8",
+ "lab_f9", "lf9",
+ "meta_off", "rmm",
+ "meta_on", "smm",
+ "newline", "_glitch",
+ "pad_char", "npc",
+ "parm_dch", "dch",
+ "parm_delete_line", "dl",
+ "parm_down_cursor", "cud",
+ "parm_ich", "ich",
+ "parm_index", "indn",
+ "parm_insert_line", "il",
+ "parm_left_cursor", "cub",
+ "parm_right_cursor", "cuf",
+ "parm_rindex", "rin",
+ "parm_up_cursor", "cuu",
+ "pkey_key", "pfkey",
+ "pkey_local", "pfloc",
+ "pkey_xmit", "pfx",
+ "print_screen", "mc0",
+ "prtr_off", "mc4",
+ "prtr_on", "mc5",
+ "repeat_char", "rep",
+ "reset_1string", "rs1",
+ "reset_2string", "rs2",
+ "reset_3string", "rs3",
+ "reset_file", "rf",
+ "restore_cursor", "rc",
+ "row_address", "mvpa",
+ "save_cursor", "row_address",
+ "scroll_forward", "ind",
+ "scroll_reverse", "ri",
+ "set_attributes", "sgr",
+ "set_tab", "hts",
+ "set_window", "wind",
+ "tab", "s_magic_smso",
+ "to_status_line", "tsl",
+ "underline_char", "uc",
+ "up_half_line", "hu",
+ "init_prog", "iprog",
+ "key_a1", "ka1",
+ "key_a3", "ka3",
+ "key_b2", "kb2",
+ "key_c1", "kc1",
+ "key_c3", "kc3",
+ "prtr_non", "mc5p",
+ "char_padding", "rmp",
+ "acs_chars", "acsc",
+ "plab_norm", "pln",
+ "key_btab", "kcbt",
+ "enter_xon_mode", "smxon",
+ "exit_xon_mode", "rmxon",
+ "enter_am_mode", "smam",
+ "exit_am_mode", "rmam",
+ "xon_character", "xonc",
+ "xoff_character", "xoffc",
+ "ena_acs", "enacs",
+ "label_on", "smln",
+ "label_off", "rmln",
+ "key_beg", "kbeg",
+ "key_cancel", "kcan",
+ "key_close", "kclo",
+ "key_command", "kcmd",
+ "key_copy", "kcpy",
+ "key_create", "kcrt",
+ "key_end", "kend",
+ "key_enter", "kent",
+ "key_exit", "kext",
+ "key_find", "kfnd",
+ "key_help", "khlp",
+ "key_mark", "kmrk",
+ "key_message", "kmsg",
+ "key_move", "kmov",
+ "key_next", "knxt",
+ "key_open", "kopn",
+ "key_options", "kopt",
+ "key_previous", "kprv",
+ "key_print", "kprt",
+ "key_redo", "krdo",
+ "key_reference", "kref",
+ "key_refresh", "krfr",
+ "key_replace", "krpl",
+ "key_restart", "krst",
+ "key_resume", "kres",
+ "key_save", "ksav",
+ "key_suspend", "kspd",
+ "key_undo", "kund",
+ "key_sbeg", "kBEG",
+ "key_scancel", "kCAN",
+ "key_scommand", "kCMD",
+ "key_scopy", "kCPY",
+ "key_screate", "kCRT",
+ "key_sdc", "kDC",
+ "key_sdl", "kDL",
+ "key_select", "kslt",
+ "key_send", "kEND",
+ "key_seol", "kEOL",
+ "key_sexit", "kEXT",
+ "key_sfind", "kFND",
+ "key_shelp", "kHLP",
+ "key_shome", "kHOM",
+ "key_sic", "kIC",
+ "key_sleft", "kLFT",
+ "key_smessage", "kMSG",
+ "key_smove", "kMOV",
+ "key_snext", "kNXT",
+ "key_soptions", "kOPT",
+ "key_sprevious", "kPRV",
+ "key_sprint", "kPRT",
+ "key_sredo", "kRDO",
+ "key_sreplace", "kRPL",
+ "key_sright", "kRIT",
+ "key_srsume", "kRES",
+ "key_ssave", "kSAV",
+ "key_ssuspend", "kSPD",
+ "key_sundo", "kUND",
+ "req_for_input", "rfi",
+ "key_f11", "kf11",
+ "key_f12", "kf12",
+ "key_f13", "kf13",
+ "key_f14", "kf14",
+ "key_f15", "kf15",
+ "key_f16", "kf16",
+ "key_f17", "kf17",
+ "key_f18", "kf18",
+ "key_f19", "kf19",
+ "key_f20", "kf20",
+ "key_f21", "kf21",
+ "key_f22", "kf22",
+ "key_f23", "kf23",
+ "key_f24", "kf24",
+ "key_f25", "kf25",
+ "key_f26", "kf26",
+ "key_f27", "kf27",
+ "key_f28", "kf28",
+ "key_f29", "kf29",
+ "key_f30", "kf30",
+ "key_f31", "kf31",
+ "key_f32", "kf32",
+ "key_f33", "kf33",
+ "key_f34", "kf34",
+ "key_f35", "kf35",
+ "key_f36", "kf36",
+ "key_f37", "kf37",
+ "key_f38", "kf38",
+ "key_f39", "kf39",
+ "key_f40", "kf40",
+ "key_f41", "kf41",
+ "key_f42", "kf42",
+ "key_f43", "kf43",
+ "key_f44", "kf44",
+ "key_f45", "kf45",
+ "key_f46", "kf46",
+ "key_f47", "kf47",
+ "key_f48", "kf48",
+ "key_f49", "kf49",
+ "key_f50", "kf50",
+ "key_f51", "kf51",
+ "key_f52", "kf52",
+ "key_f53", "kf53",
+ "key_f54", "kf54",
+ "key_f55", "kf55",
+ "key_f56", "kf56",
+ "key_f57", "kf57",
+ "key_f58", "kf58",
+ "key_f59", "kf59",
+ "key_f60", "kf60",
+ "key_f61", "kf61",
+ "key_f62", "kf62",
+ "key_f63", "kf63",
+ "clr_bol", "el1",
+ "clear_margins", "mgc",
+ "set_left_margin", "smgl",
+ "set_right_margin", "smgr",
+ "label_format", "fln",
+ "set_clock", "sclk",
+ "display_clock", "dclk",
+ "remove_clock", "rmclk",
+ "create_window", "cwin",
+ "goto_window", "wingo",
+ "hangup", "hup",
+ "dial_phone", "dial",
+ "quick_dial", "qdial",
+ "tone", "tone",
+ "pulse", "pulse",
+ "flash_hook", "hook",
+ "fixed_pause", "pause",
+ "wait_tone", "wait",
+ "user0", "u0",
+ "user1", "u1",
+ "user2", "u2",
+ "user3", "u3",
+ "user4", "u4",
+ "user5", "u5",
+ "user6", "u6",
+ "user7", "u7",
+ "user8", "u8",
+ "user9", "u9",
+ "orig_pair", "op",
+ "orig_colors", "oc",
+ "initialize_color", "initc",
+ "initialize_pair", "initp",
+ "set_color_pair", "scp",
+ "set_foreground", "setf",
+ "set_background", "setb",
+ "change_char_pitch", "cpi",
+ "change_line_pitch", "lpi",
+ "change_res_horz", "chr",
+ "change_res_vert", "cvr",
+ "define_char", "defc",
+ "enter_doublewide_mode", "swidm",
+ "enter_draft_quality", "sdrfq",
+ "enter_italics_mode", "sitm",
+ "enter_leftward_mode", "slm",
+ "enter_micro_mode", "smicm",
+ "enter_near_letter_quality", "snlq",
+ "enter_normal_quality", "snrmq",
+ "enter_shadow_mode", "sshm",
+ "enter_subscript_mode", "ssubm",
+ "enter_superscript_mode", "ssupm",
+ "enter_upward_mode", "sum",
+ "exit_doublewide_mode", "rwidm",
+ "exit_italics_mode", "ritm",
+ "exit_leftward_mode", "rlm",
+ "exit_micro_mode", "rmicm",
+ "exit_shadow_mode", "rshm",
+ "exit_subscript_mode", "rsubm",
+ "exit_superscript_mode", "rsupm",
+ "exit_upward_mode", "rum",
+ "micro_column_address", "mhpa",
+ "micro_down", "mcud1",
+ "micro_left", "mcub1",
+ "micro_right", "mcuf1",
+ "micro_row_address", "mvpa",
+ "micro_up", "mcuu1",
+ "order_of_pins", "porder",
+ "parm_down_micro", "mcud",
+ "parm_left_micro", "mcub",
+ "parm_right_micro", "mcuf",
+ "parm_up_micro", "mcuu",
+ "select_char_set", "scs",
+ "set_bottom_margin", "smgb",
+ "set_bottom_margin_parm", "smgbp",
+ "set_left_margin_parm", "smglp",
+ "set_right_margin_parm", "smgrp",
+ "set_top_margin", "smgt",
+ "set_top_margin_parm", "smgtp",
+ "start_bit_image", "sbim",
+ "start_char_set_def", "scsd",
+ "stop_bit_image", "rbim",
+ "stop_char_set_def", "rcsd",
+ "subscript_characters", "subcs",
+ "superscript_characters", "supcs",
+ "these_cause_cr", "docr",
+ "zero_motion", "zerom",
+ "char_set_names", "csnm",
+ "key_mouse", "kmous",
+ "mouse_info", "minfo",
+ "req_mouse_pos", "reqmp",
+ "get_mouse", "getm",
+ "set_a_foreground", "setaf",
+ "set_a_background", "setab",
+ "pkey_plab", "pfxl",
+ "device_type", "devt",
+ "code_set_init", "csin",
+ "set0_des_seq", "s0ds",
+ "set1_des_seq", "s1ds",
+ "set2_des_seq", "s2ds",
+ "set3_des_seq", "s3ds",
+ "set_lr_margin", "smglr",
+ "set_tb_margin", "smgtb",
+ "bit_image_repeat", "birep",
+ "bit_image_newline", "binel",
+ "bit_image_carriage_return", "bicr",
+ "color_names", "colornm",
+ "define_bit_image_region", "defbi",
+ "end_bit_image_region", "endbi",
+ "set_color_band", "setcolor",
+ "set_page_length", "slines",
+ "display_pc_char", "dispc",
+ "enter_pc_charset_mode", "smpch",
+ "exit_pc_charset_mode", "rmpch",
+ "enter_scancode_mode", "smsc",
+ "exit_scancode_mode", "rmsc",
+ "pc_term_options", "pctrm",
+ "scancode_escape", "scesc",
+ "alt_scancode_esc", "scesa",
+ "enter_horizontal_hl_mode", "ehhlm",
+ "enter_left_hl_mode", "elhlm",
+ "enter_low_hl_mode", "elohlm",
+ "enter_right_hl_mode", "erhlm",
+ "enter_top_hl_mode", "ethlm",
+ "enter_vertical_hl_mode", "evhlm",
+ "set_a_attributes", "sgr1",
+ "set_pglen_inch", "slength",
+ "termcap_init2", "",
+ "termcap_reset", "",
+ "linefeed_if_not_lf", "",
+ "backspace_if_not_bs", "",
+ "other_non_function_keys", "",
+ "arrow_key_map", "",
+ "acs_ulcorner", "",
+ "acs_llcorner", "",
+ "acs_urcorner", "",
+ "acs_lrcorner", "",
+ "acs_ltee", "",
+ "acs_rtee", "",
+ "acs_btee", "",
+ "acs_ttee", "",
+ "acs_hline", "",
+ "acs_vline", "",
+ "acs_plus", "",
+ "memory_lock", "",
+ "memory_unlock", "",
+ "box_chars_1", "",
+}
diff --git a/vendor/github.com/ijc/Gotty/gotty.go b/vendor/github.com/ijc/Gotty/gotty.go
new file mode 100644
index 000000000..c329778a1
--- /dev/null
+++ b/vendor/github.com/ijc/Gotty/gotty.go
@@ -0,0 +1,244 @@
+// Copyright 2012 Neal van Veen. All rights reserved.
+// Usage of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Gotty is a Go-package for reading and parsing the terminfo database
+package gotty
+
+// TODO add more concurrency to name lookup, look for more opportunities.
+
+import (
+ "bytes"
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "os"
+ "path"
+ "reflect"
+ "strings"
+ "sync"
+)
+
+// Open a terminfo file by the name given and construct a TermInfo object.
+// If something went wrong reading the terminfo database file, an error is
+// returned.
+func OpenTermInfo(termName string) (*TermInfo, error) {
+ if len(termName) == 0 {
+ return nil, errors.New("No termname given")
+ }
+ // Find the environment variables
+ if termloc := os.Getenv("TERMINFO"); len(termloc) > 0 {
+ return readTermInfo(path.Join(termloc, string(termName[0]), termName))
+ } else {
+ // Search like ncurses
+ locations := []string{}
+ if h := os.Getenv("HOME"); len(h) > 0 {
+ locations = append(locations, path.Join(h, ".terminfo"))
+ }
+ locations = append(locations,
+ "/etc/terminfo/",
+ "/lib/terminfo/",
+ "/usr/share/terminfo/")
+ for _, str := range locations {
+ term, err := readTermInfo(path.Join(str, string(termName[0]), termName))
+ if err == nil {
+ return term, nil
+ }
+ }
+ return nil, errors.New("No terminfo file(-location) found")
+ }
+}
+
+// Open a terminfo file from the environment variable containing the current
+// terminal name and construct a TermInfo object. If something went wrong
+// reading the terminfo database file, an error is returned.
+func OpenTermInfoEnv() (*TermInfo, error) {
+ termenv := os.Getenv("TERM")
+ return OpenTermInfo(termenv)
+}
+
+// Return an attribute by the name attr provided. If none can be found,
+// an error is returned.
+func (term *TermInfo) GetAttribute(attr string) (stacker, error) {
+ // Channel to store the main value in.
+ var value stacker
+ // Add a blocking WaitGroup
+ var block sync.WaitGroup
+ // Keep track of variable being written.
+ written := false
+ // Function to put into goroutine.
+ f := func(ats interface{}) {
+ var ok bool
+ var v stacker
+ // Switch on type of map to use and assign value to it.
+ switch reflect.TypeOf(ats).Elem().Kind() {
+ case reflect.Bool:
+ v, ok = ats.(map[string]bool)[attr]
+ case reflect.Int16:
+ v, ok = ats.(map[string]int16)[attr]
+ case reflect.String:
+ v, ok = ats.(map[string]string)[attr]
+ }
+ // If ok, a value is found, so we can write.
+ if ok {
+ value = v
+ written = true
+ }
+ // Goroutine is done
+ block.Done()
+ }
+ block.Add(3)
+ // Go for all 3 attribute lists.
+ go f(term.boolAttributes)
+ go f(term.numAttributes)
+ go f(term.strAttributes)
+ // Wait until every goroutine is done.
+ block.Wait()
+ // If a value has been written, return it.
+ if written {
+ return value, nil
+ }
+ // Otherwise, error.
+ return nil, fmt.Errorf("Erorr finding attribute")
+}
+
+// Return an attribute by the name attr provided. If none can be found,
+// an error is returned. A name is first converted to its termcap value.
+func (term *TermInfo) GetAttributeName(name string) (stacker, error) {
+ tc := GetTermcapName(name)
+ return term.GetAttribute(tc)
+}
+
+// A utility function that finds and returns the termcap equivalent of a
+// variable name.
+func GetTermcapName(name string) string {
+ // Termcap name
+ var tc string
+ // Blocking group
+ var wait sync.WaitGroup
+ // Function to put into a goroutine
+ f := func(attrs []string) {
+ // Find the string corresponding to the name
+ for i, s := range attrs {
+ if s == name {
+ tc = attrs[i+1]
+ }
+ }
+ // Goroutine is finished
+ wait.Done()
+ }
+ wait.Add(3)
+ // Go for all 3 attribute lists
+ go f(BoolAttr[:])
+ go f(NumAttr[:])
+ go f(StrAttr[:])
+ // Wait until every goroutine is done
+ wait.Wait()
+ // Return the termcap name
+ return tc
+}
+
+// This function takes a path to a terminfo file and reads it in binary
+// form to construct the actual TermInfo file.
+func readTermInfo(path string) (*TermInfo, error) {
+ // Open the terminfo file
+ file, err := os.Open(path)
+ defer file.Close()
+ if err != nil {
+ return nil, err
+ }
+
+ // magic, nameSize, boolSize, nrSNum, nrOffsetsStr, strSize
+ // Header is composed of the magic 0432 octal number, size of the name
+ // section, size of the boolean section, the amount of number values,
+ // the number of offsets of strings, and the size of the string section.
+ var header [6]int16
+ // Byte array is used to read in byte values
+ var byteArray []byte
+ // Short array is used to read in short values
+ var shArray []int16
+ // TermInfo object to store values
+ var term TermInfo
+
+ // Read in the header
+ err = binary.Read(file, binary.LittleEndian, &header)
+ if err != nil {
+ return nil, err
+ }
+ // If magic number isn't there or isn't correct, we have the wrong filetype
+ if header[0] != 0432 {
+ return nil, errors.New(fmt.Sprintf("Wrong filetype"))
+ }
+
+ // Read in the names
+ byteArray = make([]byte, header[1])
+ err = binary.Read(file, binary.LittleEndian, &byteArray)
+ if err != nil {
+ return nil, err
+ }
+ term.Names = strings.Split(string(byteArray), "|")
+
+ // Read in the booleans
+ byteArray = make([]byte, header[2])
+ err = binary.Read(file, binary.LittleEndian, &byteArray)
+ if err != nil {
+ return nil, err
+ }
+ term.boolAttributes = make(map[string]bool)
+ for i, b := range byteArray {
+ if b == 1 {
+ term.boolAttributes[BoolAttr[i*2+1]] = true
+ }
+ }
+ // If the number of bytes read is not even, a byte for alignment is added
+ // We know the header is an even number of bytes so only need to check the
+ // total of the names and booleans.
+ if (header[1]+header[2])%2 != 0 {
+ err = binary.Read(file, binary.LittleEndian, make([]byte, 1))
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ // Read in shorts
+ shArray = make([]int16, header[3])
+ err = binary.Read(file, binary.LittleEndian, &shArray)
+ if err != nil {
+ return nil, err
+ }
+ term.numAttributes = make(map[string]int16)
+ for i, n := range shArray {
+ if n != 0377 && n > -1 {
+ term.numAttributes[NumAttr[i*2+1]] = n
+ }
+ }
+
+ // Read the offsets into the short array
+ shArray = make([]int16, header[4])
+ err = binary.Read(file, binary.LittleEndian, &shArray)
+ if err != nil {
+ return nil, err
+ }
+ // Read the actual strings in the byte array
+ byteArray = make([]byte, header[5])
+ err = binary.Read(file, binary.LittleEndian, &byteArray)
+ if err != nil {
+ return nil, err
+ }
+ term.strAttributes = make(map[string]string)
+ // We get an offset, and then iterate until the string is null-terminated
+ for i, offset := range shArray {
+ if offset > -1 {
+ if int(offset) >= len(byteArray) {
+ return nil, errors.New("array out of bounds reading string section")
+ }
+ r := bytes.IndexByte(byteArray[offset:], 0)
+ if r == -1 {
+ return nil, errors.New("missing nul byte reading string section")
+ }
+ r += int(offset)
+ term.strAttributes[StrAttr[i*2+1]] = string(byteArray[offset:r])
+ }
+ }
+ return &term, nil
+}
diff --git a/vendor/github.com/ijc/Gotty/parser.go b/vendor/github.com/ijc/Gotty/parser.go
new file mode 100644
index 000000000..a9d5d23c5
--- /dev/null
+++ b/vendor/github.com/ijc/Gotty/parser.go
@@ -0,0 +1,362 @@
+// Copyright 2012 Neal van Veen. All rights reserved.
+// Usage of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package gotty
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "regexp"
+ "strconv"
+ "strings"
+)
+
+var exp = [...]string{
+ "%%",
+ "%c",
+ "%s",
+ "%p(\\d)",
+ "%P([A-z])",
+ "%g([A-z])",
+ "%'(.)'",
+ "%{([0-9]+)}",
+ "%l",
+ "%\\+|%-|%\\*|%/|%m",
+ "%&|%\\||%\\^",
+ "%=|%>|%<",
+ "%A|%O",
+ "%!|%~",
+ "%i",
+ "%(:[\\ #\\-\\+]{0,4})?(\\d+\\.\\d+|\\d+)?[doxXs]",
+ "%\\?(.*?);",
+}
+
+var regex *regexp.Regexp
+var staticVar map[byte]stacker
+
+// Parses the attribute that is received with name attr and parameters params.
+func (term *TermInfo) Parse(attr string, params ...interface{}) (string, error) {
+ // Get the attribute name first.
+ iface, err := term.GetAttribute(attr)
+ str, ok := iface.(string)
+ if err != nil {
+ return "", err
+ }
+ if !ok {
+ return str, errors.New("Only string capabilities can be parsed.")
+ }
+ // Construct the hidden parser struct so we can use a recursive stack based
+ // parser.
+ ps := &parser{}
+ // Dynamic variables only exist in this context.
+ ps.dynamicVar = make(map[byte]stacker, 26)
+ ps.parameters = make([]stacker, len(params))
+ // Convert the parameters to insert them into the parser struct.
+ for i, x := range params {
+ ps.parameters[i] = x
+ }
+ // Recursively walk and return.
+ result, err := ps.walk(str)
+ return result, err
+}
+
+// Parses the attribute that is received with name attr and parameters params.
+// Only works on full name of a capability that is given, which it uses to
+// search for the termcap name.
+func (term *TermInfo) ParseName(attr string, params ...interface{}) (string, error) {
+ tc := GetTermcapName(attr)
+ return term.Parse(tc, params)
+}
+
+// Identify each token in a stack based manner and do the actual parsing.
+func (ps *parser) walk(attr string) (string, error) {
+ // We use a buffer to get the modified string.
+ var buf bytes.Buffer
+ // Next, find and identify all tokens by their indices and strings.
+ tokens := regex.FindAllStringSubmatch(attr, -1)
+ if len(tokens) == 0 {
+ return attr, nil
+ }
+ indices := regex.FindAllStringIndex(attr, -1)
+ q := 0 // q counts the matches of one token
+ // Iterate through the string per character.
+ for i := 0; i < len(attr); i++ {
+ // If the current position is an identified token, execute the following
+ // steps.
+ if q < len(indices) && i >= indices[q][0] && i < indices[q][1] {
+ // Switch on token.
+ switch {
+ case tokens[q][0][:2] == "%%":
+ // Literal percentage character.
+ buf.WriteByte('%')
+ case tokens[q][0][:2] == "%c":
+ // Pop a character.
+ c, err := ps.st.pop()
+ if err != nil {
+ return buf.String(), err
+ }
+ buf.WriteByte(c.(byte))
+ case tokens[q][0][:2] == "%s":
+ // Pop a string.
+ str, err := ps.st.pop()
+ if err != nil {
+ return buf.String(), err
+ }
+ if _, ok := str.(string); !ok {
+ return buf.String(), errors.New("Stack head is not a string")
+ }
+ buf.WriteString(str.(string))
+ case tokens[q][0][:2] == "%p":
+ // Push a parameter on the stack.
+ index, err := strconv.ParseInt(tokens[q][1], 10, 8)
+ index--
+ if err != nil {
+ return buf.String(), err
+ }
+ if int(index) >= len(ps.parameters) {
+ return buf.String(), errors.New("Parameters index out of bound")
+ }
+ ps.st.push(ps.parameters[index])
+ case tokens[q][0][:2] == "%P":
+ // Pop a variable from the stack as a dynamic or static variable.
+ val, err := ps.st.pop()
+ if err != nil {
+ return buf.String(), err
+ }
+ index := tokens[q][2]
+ if len(index) > 1 {
+ errorStr := fmt.Sprintf("%s is not a valid dynamic variables index",
+ index)
+ return buf.String(), errors.New(errorStr)
+ }
+ // Specify either dynamic or static.
+ if index[0] >= 'a' && index[0] <= 'z' {
+ ps.dynamicVar[index[0]] = val
+ } else if index[0] >= 'A' && index[0] <= 'Z' {
+ staticVar[index[0]] = val
+ }
+ case tokens[q][0][:2] == "%g":
+ // Push a variable from the stack as a dynamic or static variable.
+ index := tokens[q][3]
+ if len(index) > 1 {
+ errorStr := fmt.Sprintf("%s is not a valid static variables index",
+ index)
+ return buf.String(), errors.New(errorStr)
+ }
+ var val stacker
+ if index[0] >= 'a' && index[0] <= 'z' {
+ val = ps.dynamicVar[index[0]]
+ } else if index[0] >= 'A' && index[0] <= 'Z' {
+ val = staticVar[index[0]]
+ }
+ ps.st.push(val)
+ case tokens[q][0][:2] == "%'":
+ // Push a character constant.
+ con := tokens[q][4]
+ if len(con) > 1 {
+ errorStr := fmt.Sprintf("%s is not a valid character constant", con)
+ return buf.String(), errors.New(errorStr)
+ }
+ ps.st.push(con[0])
+ case tokens[q][0][:2] == "%{":
+ // Push an integer constant.
+ con, err := strconv.ParseInt(tokens[q][5], 10, 32)
+ if err != nil {
+ return buf.String(), err
+ }
+ ps.st.push(con)
+ case tokens[q][0][:2] == "%l":
+ // Push the length of the string that is popped from the stack.
+ popStr, err := ps.st.pop()
+ if err != nil {
+ return buf.String(), err
+ }
+ if _, ok := popStr.(string); !ok {
+ errStr := fmt.Sprintf("Stack head is not a string")
+ return buf.String(), errors.New(errStr)
+ }
+ ps.st.push(len(popStr.(string)))
+ case tokens[q][0][:2] == "%?":
+ // If-then-else construct. First, the whole string is identified and
+ // then inside this substring, we can specify which parts to switch on.
+ ifReg, _ := regexp.Compile("%\\?(.*)%t(.*)%e(.*);|%\\?(.*)%t(.*);")
+ ifTokens := ifReg.FindStringSubmatch(tokens[q][0])
+ var (
+ ifStr string
+ err error
+ )
+ // Parse the if-part to determine if-else.
+ if len(ifTokens[1]) > 0 {
+ ifStr, err = ps.walk(ifTokens[1])
+ } else { // else
+ ifStr, err = ps.walk(ifTokens[4])
+ }
+ // Return any errors
+ if err != nil {
+ return buf.String(), err
+ } else if len(ifStr) > 0 {
+ // Self-defined limitation, not sure if this is correct, but didn't
+ // seem like it.
+ return buf.String(), errors.New("If-clause cannot print statements")
+ }
+ var thenStr string
+ // Pop the first value that is set by parsing the if-clause.
+ choose, err := ps.st.pop()
+ if err != nil {
+ return buf.String(), err
+ }
+ // Switch to if or else.
+ if choose.(int) == 0 && len(ifTokens[1]) > 0 {
+ thenStr, err = ps.walk(ifTokens[3])
+ } else if choose.(int) != 0 {
+ if len(ifTokens[1]) > 0 {
+ thenStr, err = ps.walk(ifTokens[2])
+ } else {
+ thenStr, err = ps.walk(ifTokens[5])
+ }
+ }
+ if err != nil {
+ return buf.String(), err
+ }
+ buf.WriteString(thenStr)
+ case tokens[q][0][len(tokens[q][0])-1] == 'd': // Fallthrough for printing
+ fallthrough
+ case tokens[q][0][len(tokens[q][0])-1] == 'o': // digits.
+ fallthrough
+ case tokens[q][0][len(tokens[q][0])-1] == 'x':
+ fallthrough
+ case tokens[q][0][len(tokens[q][0])-1] == 'X':
+ fallthrough
+ case tokens[q][0][len(tokens[q][0])-1] == 's':
+ token := tokens[q][0]
+ // Remove the : that comes before a flag.
+ if token[1] == ':' {
+ token = token[:1] + token[2:]
+ }
+ digit, err := ps.st.pop()
+ if err != nil {
+ return buf.String(), err
+ }
+ // The rest is determined like the normal formatted prints.
+ digitStr := fmt.Sprintf(token, digit.(int))
+ buf.WriteString(digitStr)
+ case tokens[q][0][:2] == "%i":
+ // Increment the parameters by one.
+ if len(ps.parameters) < 2 {
+ return buf.String(), errors.New("Not enough parameters to increment.")
+ }
+ val1, val2 := ps.parameters[0].(int), ps.parameters[1].(int)
+ val1++
+ val2++
+ ps.parameters[0], ps.parameters[1] = val1, val2
+ default:
+ // The rest of the tokens is a special case, where two values are
+ // popped and then operated on by the token that comes after them.
+ op1, err := ps.st.pop()
+ if err != nil {
+ return buf.String(), err
+ }
+ op2, err := ps.st.pop()
+ if err != nil {
+ return buf.String(), err
+ }
+ var result stacker
+ switch tokens[q][0][:2] {
+ case "%+":
+ // Addition
+ result = op2.(int) + op1.(int)
+ case "%-":
+ // Subtraction
+ result = op2.(int) - op1.(int)
+ case "%*":
+ // Multiplication
+ result = op2.(int) * op1.(int)
+ case "%/":
+ // Division
+ result = op2.(int) / op1.(int)
+ case "%m":
+ // Modulo
+ result = op2.(int) % op1.(int)
+ case "%&":
+ // Bitwise AND
+ result = op2.(int) & op1.(int)
+ case "%|":
+ // Bitwise OR
+ result = op2.(int) | op1.(int)
+ case "%^":
+ // Bitwise XOR
+ result = op2.(int) ^ op1.(int)
+ case "%=":
+ // Equals
+ result = op2 == op1
+ case "%>":
+ // Greater-than
+ result = op2.(int) > op1.(int)
+ case "%<":
+ // Lesser-than
+ result = op2.(int) < op1.(int)
+ case "%A":
+ // Logical AND
+ result = op2.(bool) && op1.(bool)
+ case "%O":
+ // Logical OR
+ result = op2.(bool) || op1.(bool)
+ case "%!":
+ // Logical complement
+ result = !op1.(bool)
+ case "%~":
+ // Bitwise complement
+ result = ^(op1.(int))
+ }
+ ps.st.push(result)
+ }
+
+ i = indices[q][1] - 1
+ q++
+ } else {
+ // We are not "inside" a token, so just skip until the end or the next
+ // token, and add all characters to the buffer.
+ j := i
+ if q != len(indices) {
+ for !(j >= indices[q][0] && j < indices[q][1]) {
+ j++
+ }
+ } else {
+ j = len(attr)
+ }
+ buf.WriteString(string(attr[i:j]))
+ i = j
+ }
+ }
+ // Return the buffer as a string.
+ return buf.String(), nil
+}
+
+// Push a stacker-value onto the stack.
+func (st *stack) push(s stacker) {
+ *st = append(*st, s)
+}
+
+// Pop a stacker-value from the stack.
+func (st *stack) pop() (stacker, error) {
+ if len(*st) == 0 {
+ return nil, errors.New("Stack is empty.")
+ }
+ newStack := make(stack, len(*st)-1)
+ val := (*st)[len(*st)-1]
+ copy(newStack, (*st)[:len(*st)-1])
+ *st = newStack
+ return val, nil
+}
+
+// Initialize regexes and the static vars (that don't get changed between
+// calls.
+func init() {
+ // Initialize the main regex.
+ expStr := strings.Join(exp[:], "|")
+ regex, _ = regexp.Compile(expStr)
+ // Initialize the static variables.
+ staticVar = make(map[byte]stacker, 26)
+}
diff --git a/vendor/github.com/ijc/Gotty/types.go b/vendor/github.com/ijc/Gotty/types.go
new file mode 100644
index 000000000..9bcc65e9b
--- /dev/null
+++ b/vendor/github.com/ijc/Gotty/types.go
@@ -0,0 +1,23 @@
+// Copyright 2012 Neal van Veen. All rights reserved.
+// Usage of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package gotty
+
+type TermInfo struct {
+ boolAttributes map[string]bool
+ numAttributes map[string]int16
+ strAttributes map[string]string
+ // The various names of the TermInfo file.
+ Names []string
+}
+
+type stacker interface {
+}
+type stack []stacker
+
+type parser struct {
+ st stack
+ parameters []stacker
+ dynamicVar map[byte]stacker
+}