Comparison

util/human/io.lua @ 11120:b2331f3dfeea

Merge 0.11->trunk
author Matthew Wild <mwild1@gmail.com>
date Wed, 30 Sep 2020 09:50:33 +0100
parent 10917:1eb83bc6f706
child 11892:e712133b4de1
comparison
equal deleted inserted replaced
11119:68df52bf08d5 11120:b2331f3dfeea
1 local array = require "util.array";
2
3 local function getchar(n)
4 local stty_ret = os.execute("stty raw -echo 2>/dev/null");
5 local ok, char;
6 if stty_ret == true or stty_ret == 0 then
7 ok, char = pcall(io.read, n or 1);
8 os.execute("stty sane");
9 else
10 ok, char = pcall(io.read, "*l");
11 if ok then
12 char = char:sub(1, n or 1);
13 end
14 end
15 if ok then
16 return char;
17 end
18 end
19
20 local function getline()
21 local ok, line = pcall(io.read, "*l");
22 if ok then
23 return line;
24 end
25 end
26
27 local function getpass()
28 local stty_ret, _, status_code = os.execute("stty -echo 2>/dev/null");
29 if status_code then -- COMPAT w/ Lua 5.1
30 stty_ret = status_code;
31 end
32 if stty_ret ~= 0 then
33 io.write("\027[08m"); -- ANSI 'hidden' text attribute
34 end
35 local ok, pass = pcall(io.read, "*l");
36 if stty_ret == 0 then
37 os.execute("stty sane");
38 else
39 io.write("\027[00m");
40 end
41 io.write("\n");
42 if ok then
43 return pass;
44 end
45 end
46
47 local function show_yesno(prompt)
48 io.write(prompt, " ");
49 local choice = getchar():lower();
50 io.write("\n");
51 if not choice:match("%a") then
52 choice = prompt:match("%[.-(%U).-%]$");
53 if not choice then return nil; end
54 end
55 return (choice == "y");
56 end
57
58 local function read_password()
59 local password;
60 while true do
61 io.write("Enter new password: ");
62 password = getpass();
63 if not password then
64 print("No password - cancelled");
65 return;
66 end
67 io.write("Retype new password: ");
68 if getpass() ~= password then
69 if not show_yesno [=[Passwords did not match, try again? [Y/n]]=] then
70 return;
71 end
72 else
73 break;
74 end
75 end
76 return password;
77 end
78
79 local function show_prompt(prompt)
80 io.write(prompt, " ");
81 local line = getline();
82 line = line and line:gsub("\n$","");
83 return (line and #line > 0) and line or nil;
84 end
85
86 local function printf(fmt, ...)
87 print(fmt:format(...));
88 end
89
90 local function padright(s, width)
91 return s..string.rep(" ", width-#s);
92 end
93
94 local function padleft(s, width)
95 return string.rep(" ", width-#s)..s;
96 end
97
98 local function new_table(col_specs, max_width)
99 max_width = max_width or tonumber(os.getenv("COLUMNS")) or 80;
100 local separator = " | ";
101
102 local widths = {};
103 local total_width = max_width - #separator * (#col_specs-1);
104 local free_width = total_width;
105 -- Calculate width of fixed-size columns
106 for i = 1, #col_specs do
107 local width = col_specs[i].width or "0";
108 if not(type(width) == "string" and width:sub(-1) == "%") then
109 local title = col_specs[i].title;
110 width = math.max(tonumber(width), title and (#title+1) or 0);
111 widths[i] = width;
112 free_width = free_width - width;
113 if i > 1 then
114 free_width = free_width - #separator;
115 end
116 end
117 end
118 -- Calculate width of %-based columns
119 for i = 1, #col_specs do
120 if not widths[i] then
121 local pc_width = tonumber((col_specs[i].width:gsub("%%$", "")));
122 widths[i] = math.floor(free_width*(pc_width/100));
123 end
124 end
125
126 return function (row)
127 local titles;
128 if not row then
129 titles, row = true, array.pluck(col_specs, "title", "");
130 end
131 local output = {};
132 for i, column in ipairs(col_specs) do
133 local width = widths[i];
134 local v = (not titles and column.mapper or tostring)(row[not titles and column.key or i] or "", row);
135 if #v < width then
136 if column.align == "right" then
137 v = padleft(v, width);
138 else
139 v = padright(v, width);
140 end
141 elseif #v > width then
142 v = v:sub(1, width-1) .. "…";
143 end
144 table.insert(output, v);
145 end
146 return table.concat(output, separator);
147 end;
148 end
149
150 return {
151 getchar = getchar;
152 getline = getline;
153 getpass = getpass;
154 show_yesno = show_yesno;
155 read_password = read_password;
156 show_prompt = show_prompt;
157 printf = printf;
158 padleft = padleft;
159 padright = padright;
160 table = new_table;
161 };