annotate util/human/io.lua @ 13946:f5e8ab42c708

mod_http_file_share: Check that files are still there with correct size Failed uploads can leave behind unused slots. Files shouldn't change size after they have been successfully uploaded, but might as well double check it.
author Kim Alvefur <zash@zash.se>
date Sat, 04 Dec 2021 18:56:51 +0100
parents cfe3e85e715f
children 7008869fcce2
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
12975
d10957394a3c util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12783
diff changeset
1 local array = require "prosody.util.array";
13210
8dbe693ded6b util.human.io: Fix stray 'stty' error by only querying width of real ttys
Kim Alvefur <zash@zash.se>
parents: 13199
diff changeset
2 local pposix = require "prosody.util.pposix";
12975
d10957394a3c util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12783
diff changeset
3 local utf8 = rawget(_G, "utf8") or require"prosody.util.encodings".utf8;
11896
93e9f7ae2f9b util.human.io: Fix cutting of UTF-8 into pieces
Kim Alvefur <zash@zash.se>
parents: 11895
diff changeset
4 local len = utf8.len or function(s)
93e9f7ae2f9b util.human.io: Fix cutting of UTF-8 into pieces
Kim Alvefur <zash@zash.se>
parents: 11895
diff changeset
5 local _, count = s:gsub("[%z\001-\127\194-\253][\128-\191]*", "");
93e9f7ae2f9b util.human.io: Fix cutting of UTF-8 into pieces
Kim Alvefur <zash@zash.se>
parents: 11895
diff changeset
6 return count;
93e9f7ae2f9b util.human.io: Fix cutting of UTF-8 into pieces
Kim Alvefur <zash@zash.se>
parents: 11895
diff changeset
7 end;
10894
d15a4284fdf8 util.human.io: table: Return title row when no row data passed
Matthew Wild <mwild1@gmail.com>
parents: 10893
diff changeset
8
10870
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
9 local function getchar(n)
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
10 local stty_ret = os.execute("stty raw -echo 2>/dev/null");
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
11 local ok, char;
12783
d513e4bd4928 util.human.io: Fix handling of os.execute() return values in Lua 5.2+
Kim Alvefur <zash@zash.se>
parents: 12573
diff changeset
12 if stty_ret then
10870
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
13 ok, char = pcall(io.read, n or 1);
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
14 os.execute("stty sane");
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
15 else
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
16 ok, char = pcall(io.read, "*l");
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
17 if ok then
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
18 char = char:sub(1, n or 1);
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
19 end
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
20 end
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
21 if ok then
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
22 return char;
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
23 end
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
24 end
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
25
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
26 local function getline()
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
27 local ok, line = pcall(io.read, "*l");
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
28 if ok then
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
29 return line;
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
30 end
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
31 end
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
32
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
33 local function getpass()
12573
0f4feaf9ca64 util: Remove various Lua 5.1 compatibility hacks
Kim Alvefur <zash@zash.se>
parents: 11897
diff changeset
34 local stty_ret = os.execute("stty -echo 2>/dev/null");
12783
d513e4bd4928 util.human.io: Fix handling of os.execute() return values in Lua 5.2+
Kim Alvefur <zash@zash.se>
parents: 12573
diff changeset
35 if not stty_ret then
10870
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
36 io.write("\027[08m"); -- ANSI 'hidden' text attribute
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
37 end
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
38 local ok, pass = pcall(io.read, "*l");
12783
d513e4bd4928 util.human.io: Fix handling of os.execute() return values in Lua 5.2+
Kim Alvefur <zash@zash.se>
parents: 12573
diff changeset
39 if stty_ret then
10870
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
40 os.execute("stty sane");
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
41 else
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
42 io.write("\027[00m");
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
43 end
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
44 io.write("\n");
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
45 if ok then
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
46 return pass;
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
47 end
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
48 end
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
49
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
50 local function show_yesno(prompt)
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
51 io.write(prompt, " ");
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
52 local choice = getchar():lower();
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
53 io.write("\n");
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
54 if not choice:match("%a") then
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
55 choice = prompt:match("%[.-(%U).-%]$");
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
56 if not choice then return nil; end
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
57 end
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
58 return (choice == "y");
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
59 end
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
60
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
61 local function read_password()
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
62 local password;
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
63 while true do
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
64 io.write("Enter new password: ");
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
65 password = getpass();
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
66 if not password then
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
67 print("No password - cancelled");
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
68 return;
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
69 end
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
70 io.write("Retype new password: ");
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
71 if getpass() ~= password then
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
72 if not show_yesno [=[Passwords did not match, try again? [Y/n]]=] then
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
73 return;
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
74 end
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
75 else
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
76 break;
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
77 end
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
78 end
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
79 return password;
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
80 end
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
81
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
82 local function show_prompt(prompt)
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
83 io.write(prompt, " ");
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
84 local line = getline();
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
85 line = line and line:gsub("\n$","");
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
86 return (line and #line > 0) and line or nil;
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
87 end
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
88
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
89 local function printf(fmt, ...)
10872
a3f3f42736f2 util.human.io: Fix variable name [luacheck]
Matthew Wild <mwild1@gmail.com>
parents: 10870
diff changeset
90 print(fmt:format(...));
10870
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
91 end
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
92
10891
8d47858805c9 util.human.io: Add padleft, padright and a table printing function
Matthew Wild <mwild1@gmail.com>
parents: 10872
diff changeset
93 local function padright(s, width)
11897
e84ea5b58b29 util.human.io: Use UTF-8-aware length check in padding functions
Kim Alvefur <zash@zash.se>
parents: 11896
diff changeset
94 return s..string.rep(" ", width-len(s));
10891
8d47858805c9 util.human.io: Add padleft, padright and a table printing function
Matthew Wild <mwild1@gmail.com>
parents: 10872
diff changeset
95 end
8d47858805c9 util.human.io: Add padleft, padright and a table printing function
Matthew Wild <mwild1@gmail.com>
parents: 10872
diff changeset
96
8d47858805c9 util.human.io: Add padleft, padright and a table printing function
Matthew Wild <mwild1@gmail.com>
parents: 10872
diff changeset
97 local function padleft(s, width)
11897
e84ea5b58b29 util.human.io: Use UTF-8-aware length check in padding functions
Kim Alvefur <zash@zash.se>
parents: 11896
diff changeset
98 return string.rep(" ", width-len(s))..s;
10891
8d47858805c9 util.human.io: Add padleft, padright and a table printing function
Matthew Wild <mwild1@gmail.com>
parents: 10872
diff changeset
99 end
8d47858805c9 util.human.io: Add padleft, padright and a table printing function
Matthew Wild <mwild1@gmail.com>
parents: 10872
diff changeset
100
11896
93e9f7ae2f9b util.human.io: Fix cutting of UTF-8 into pieces
Kim Alvefur <zash@zash.se>
parents: 11895
diff changeset
101 local pat = "[%z\001-\127\194-\253][\128-\191]*";
93e9f7ae2f9b util.human.io: Fix cutting of UTF-8 into pieces
Kim Alvefur <zash@zash.se>
parents: 11895
diff changeset
102 local function utf8_cut(s, pos)
93e9f7ae2f9b util.human.io: Fix cutting of UTF-8 into pieces
Kim Alvefur <zash@zash.se>
parents: 11895
diff changeset
103 return s:match("^"..pat:rep(pos)) or s;
93e9f7ae2f9b util.human.io: Fix cutting of UTF-8 into pieces
Kim Alvefur <zash@zash.se>
parents: 11895
diff changeset
104 end
93e9f7ae2f9b util.human.io: Fix cutting of UTF-8 into pieces
Kim Alvefur <zash@zash.se>
parents: 11895
diff changeset
105
93e9f7ae2f9b util.human.io: Fix cutting of UTF-8 into pieces
Kim Alvefur <zash@zash.se>
parents: 11895
diff changeset
106 if utf8.len and utf8.offset then
93e9f7ae2f9b util.human.io: Fix cutting of UTF-8 into pieces
Kim Alvefur <zash@zash.se>
parents: 11895
diff changeset
107 function utf8_cut(s, pos)
93e9f7ae2f9b util.human.io: Fix cutting of UTF-8 into pieces
Kim Alvefur <zash@zash.se>
parents: 11895
diff changeset
108 return s:sub(1, utf8.offset(s, pos+1)-1);
93e9f7ae2f9b util.human.io: Fix cutting of UTF-8 into pieces
Kim Alvefur <zash@zash.se>
parents: 11895
diff changeset
109 end
93e9f7ae2f9b util.human.io: Fix cutting of UTF-8 into pieces
Kim Alvefur <zash@zash.se>
parents: 11895
diff changeset
110 end
93e9f7ae2f9b util.human.io: Fix cutting of UTF-8 into pieces
Kim Alvefur <zash@zash.se>
parents: 11895
diff changeset
111
13044
5bd272095388 util.human.io: Add term_width() method to discover the terminal width
Matthew Wild <mwild1@gmail.com>
parents: 13040
diff changeset
112 local function term_width(default)
13051
164c2787901a util.human.io: Coerce $COLUMNS to number
Kim Alvefur <zash@zash.se>
parents: 13049
diff changeset
113 local env_cols = tonumber(os.getenv "COLUMNS");
13047
d939bf469057 util.human.io: Prefer using the $COLUMNS environment variable if set (by readline)
Kim Alvefur <zash@zash.se>
parents: 13045
diff changeset
114 if env_cols then return env_cols; end
13210
8dbe693ded6b util.human.io: Fix stray 'stty' error by only querying width of real ttys
Kim Alvefur <zash@zash.se>
parents: 13199
diff changeset
115 if not pposix.isatty(io.stdout) then
8dbe693ded6b util.human.io: Fix stray 'stty' error by only querying width of real ttys
Kim Alvefur <zash@zash.se>
parents: 13199
diff changeset
116 return default;
8dbe693ded6b util.human.io: Fix stray 'stty' error by only querying width of real ttys
Kim Alvefur <zash@zash.se>
parents: 13199
diff changeset
117 end
13044
5bd272095388 util.human.io: Add term_width() method to discover the terminal width
Matthew Wild <mwild1@gmail.com>
parents: 13040
diff changeset
118 local stty = io.popen("stty -a");
5bd272095388 util.human.io: Add term_width() method to discover the terminal width
Matthew Wild <mwild1@gmail.com>
parents: 13040
diff changeset
119 if not stty then return default; end
5bd272095388 util.human.io: Add term_width() method to discover the terminal width
Matthew Wild <mwild1@gmail.com>
parents: 13040
diff changeset
120 local result = stty:read("*a");
5bd272095388 util.human.io: Add term_width() method to discover the terminal width
Matthew Wild <mwild1@gmail.com>
parents: 13040
diff changeset
121 if result then
5bd272095388 util.human.io: Add term_width() method to discover the terminal width
Matthew Wild <mwild1@gmail.com>
parents: 13040
diff changeset
122 result = result:match("%f[%w]columns[ =]*(%d+)");
5bd272095388 util.human.io: Add term_width() method to discover the terminal width
Matthew Wild <mwild1@gmail.com>
parents: 13040
diff changeset
123 end
5bd272095388 util.human.io: Add term_width() method to discover the terminal width
Matthew Wild <mwild1@gmail.com>
parents: 13040
diff changeset
124 stty:close();
5bd272095388 util.human.io: Add term_width() method to discover the terminal width
Matthew Wild <mwild1@gmail.com>
parents: 13040
diff changeset
125 return tonumber(result or default);
5bd272095388 util.human.io: Add term_width() method to discover the terminal width
Matthew Wild <mwild1@gmail.com>
parents: 13040
diff changeset
126 end
5bd272095388 util.human.io: Add term_width() method to discover the terminal width
Matthew Wild <mwild1@gmail.com>
parents: 13040
diff changeset
127
11894
57106c61d104 util.human.io: Factor out ellipsis function
Kim Alvefur <zash@zash.se>
parents: 11893
diff changeset
128 local function ellipsis(s, width)
11896
93e9f7ae2f9b util.human.io: Fix cutting of UTF-8 into pieces
Kim Alvefur <zash@zash.se>
parents: 11895
diff changeset
129 if len(s) <= width then return s; end
13067
386ca97bec5b util.human.io: Fix error with ellipsis to negative length
Kim Alvefur <zash@zash.se>
parents: 13054
diff changeset
130 if width <= 1 then return "…"; end
11896
93e9f7ae2f9b util.human.io: Fix cutting of UTF-8 into pieces
Kim Alvefur <zash@zash.se>
parents: 11895
diff changeset
131 return utf8_cut(s, width - 1) .. "…";
11894
57106c61d104 util.human.io: Factor out ellipsis function
Kim Alvefur <zash@zash.se>
parents: 11893
diff changeset
132 end
57106c61d104 util.human.io: Factor out ellipsis function
Kim Alvefur <zash@zash.se>
parents: 11893
diff changeset
133
13935
6a493e41c2cc util.human.io: Factor out column width calculation
Kim Alvefur <zash@zash.se>
parents: 13367
diff changeset
134 local function calculate_column_widths(col_specs, separator, max_width)
10891
8d47858805c9 util.human.io: Add padleft, padright and a table printing function
Matthew Wild <mwild1@gmail.com>
parents: 10872
diff changeset
135 local widths = {};
10907
6af28c756752 util.human.io: Draw a separator between columns
Kim Alvefur <zash@zash.se>
parents: 10904
diff changeset
136 local total_width = max_width - #separator * (#col_specs-1);
10891
8d47858805c9 util.human.io: Add padleft, padright and a table printing function
Matthew Wild <mwild1@gmail.com>
parents: 10872
diff changeset
137 local free_width = total_width;
8d47858805c9 util.human.io: Add padleft, padright and a table printing function
Matthew Wild <mwild1@gmail.com>
parents: 10872
diff changeset
138 -- Calculate width of fixed-size columns
8d47858805c9 util.human.io: Add padleft, padright and a table printing function
Matthew Wild <mwild1@gmail.com>
parents: 10872
diff changeset
139 for i = 1, #col_specs do
8d47858805c9 util.human.io: Add padleft, padright and a table printing function
Matthew Wild <mwild1@gmail.com>
parents: 10872
diff changeset
140 local width = col_specs[i].width or "0";
13030
1f89a2a9f532 util.human.io: Support for dynamic "proportional" columns
Matthew Wild <mwild1@gmail.com>
parents: 12975
diff changeset
141 if not (type(width) == "string" and width:match("[p%%]$")) then
10891
8d47858805c9 util.human.io: Add padleft, padright and a table printing function
Matthew Wild <mwild1@gmail.com>
parents: 10872
diff changeset
142 local title = col_specs[i].title;
8d47858805c9 util.human.io: Add padleft, padright and a table printing function
Matthew Wild <mwild1@gmail.com>
parents: 10872
diff changeset
143 width = math.max(tonumber(width), title and (#title+1) or 0);
8d47858805c9 util.human.io: Add padleft, padright and a table printing function
Matthew Wild <mwild1@gmail.com>
parents: 10872
diff changeset
144 widths[i] = width;
8d47858805c9 util.human.io: Add padleft, padright and a table printing function
Matthew Wild <mwild1@gmail.com>
parents: 10872
diff changeset
145 free_width = free_width - width;
8d47858805c9 util.human.io: Add padleft, padright and a table printing function
Matthew Wild <mwild1@gmail.com>
parents: 10872
diff changeset
146 end
8d47858805c9 util.human.io: Add padleft, padright and a table printing function
Matthew Wild <mwild1@gmail.com>
parents: 10872
diff changeset
147 end
13030
1f89a2a9f532 util.human.io: Support for dynamic "proportional" columns
Matthew Wild <mwild1@gmail.com>
parents: 12975
diff changeset
148
1f89a2a9f532 util.human.io: Support for dynamic "proportional" columns
Matthew Wild <mwild1@gmail.com>
parents: 12975
diff changeset
149 -- Calculate width of proportional columns
1f89a2a9f532 util.human.io: Support for dynamic "proportional" columns
Matthew Wild <mwild1@gmail.com>
parents: 12975
diff changeset
150 local total_proportional_width = 0;
10891
8d47858805c9 util.human.io: Add padleft, padright and a table printing function
Matthew Wild <mwild1@gmail.com>
parents: 10872
diff changeset
151 for i = 1, #col_specs do
8d47858805c9 util.human.io: Add padleft, padright and a table printing function
Matthew Wild <mwild1@gmail.com>
parents: 10872
diff changeset
152 if not widths[i] then
13031
1023c3faffac util.human.io: Fix pattern to support fractional proportions
Matthew Wild <mwild1@gmail.com>
parents: 13030
diff changeset
153 local width_spec = col_specs[i].width:match("([%d%.]+)[p%%]");
13030
1f89a2a9f532 util.human.io: Support for dynamic "proportional" columns
Matthew Wild <mwild1@gmail.com>
parents: 12975
diff changeset
154 total_proportional_width = total_proportional_width + tonumber(width_spec);
1f89a2a9f532 util.human.io: Support for dynamic "proportional" columns
Matthew Wild <mwild1@gmail.com>
parents: 12975
diff changeset
155 end
1f89a2a9f532 util.human.io: Support for dynamic "proportional" columns
Matthew Wild <mwild1@gmail.com>
parents: 12975
diff changeset
156 end
1f89a2a9f532 util.human.io: Support for dynamic "proportional" columns
Matthew Wild <mwild1@gmail.com>
parents: 12975
diff changeset
157
1f89a2a9f532 util.human.io: Support for dynamic "proportional" columns
Matthew Wild <mwild1@gmail.com>
parents: 12975
diff changeset
158 for i = 1, #col_specs do
1f89a2a9f532 util.human.io: Support for dynamic "proportional" columns
Matthew Wild <mwild1@gmail.com>
parents: 12975
diff changeset
159 if not widths[i] then
13031
1023c3faffac util.human.io: Fix pattern to support fractional proportions
Matthew Wild <mwild1@gmail.com>
parents: 13030
diff changeset
160 local width_spec = col_specs[i].width:match("([%d%.]+)[p%%]");
13030
1f89a2a9f532 util.human.io: Support for dynamic "proportional" columns
Matthew Wild <mwild1@gmail.com>
parents: 12975
diff changeset
161 local rel_width = tonumber(width_spec);
1f89a2a9f532 util.human.io: Support for dynamic "proportional" columns
Matthew Wild <mwild1@gmail.com>
parents: 12975
diff changeset
162 widths[i] = math.floor(free_width*(rel_width/total_proportional_width));
10891
8d47858805c9 util.human.io: Add padleft, padright and a table printing function
Matthew Wild <mwild1@gmail.com>
parents: 10872
diff changeset
163 end
8d47858805c9 util.human.io: Add padleft, padright and a table printing function
Matthew Wild <mwild1@gmail.com>
parents: 10872
diff changeset
164 end
8d47858805c9 util.human.io: Add padleft, padright and a table printing function
Matthew Wild <mwild1@gmail.com>
parents: 10872
diff changeset
165
13935
6a493e41c2cc util.human.io: Factor out column width calculation
Kim Alvefur <zash@zash.se>
parents: 13367
diff changeset
166 return widths;
6a493e41c2cc util.human.io: Factor out column width calculation
Kim Alvefur <zash@zash.se>
parents: 13367
diff changeset
167 end
6a493e41c2cc util.human.io: Factor out column width calculation
Kim Alvefur <zash@zash.se>
parents: 13367
diff changeset
168
13936
4f1b6f6e68c0 util.human.io: Allow specifying a different column separator
Kim Alvefur <zash@zash.se>
parents: 13935
diff changeset
169 local function new_table(col_specs, max_width, separator)
4f1b6f6e68c0 util.human.io: Allow specifying a different column separator
Kim Alvefur <zash@zash.se>
parents: 13935
diff changeset
170 separator = separator or " | ";
13935
6a493e41c2cc util.human.io: Factor out column width calculation
Kim Alvefur <zash@zash.se>
parents: 13367
diff changeset
171
13937
cfe3e85e715f util.human.io: Support disabling column widths
Kim Alvefur <zash@zash.se>
parents: 13936
diff changeset
172 local widths;
cfe3e85e715f util.human.io: Support disabling column widths
Kim Alvefur <zash@zash.se>
parents: 13936
diff changeset
173 if max_width ~= -1 then
cfe3e85e715f util.human.io: Support disabling column widths
Kim Alvefur <zash@zash.se>
parents: 13936
diff changeset
174 max_width = max_width or term_width(80);
cfe3e85e715f util.human.io: Support disabling column widths
Kim Alvefur <zash@zash.se>
parents: 13936
diff changeset
175 widths = calculate_column_widths(col_specs, separator, max_width)
cfe3e85e715f util.human.io: Support disabling column widths
Kim Alvefur <zash@zash.se>
parents: 13936
diff changeset
176 else
cfe3e85e715f util.human.io: Support disabling column widths
Kim Alvefur <zash@zash.se>
parents: 13936
diff changeset
177 widths = {};
cfe3e85e715f util.human.io: Support disabling column widths
Kim Alvefur <zash@zash.se>
parents: 13936
diff changeset
178 end
13935
6a493e41c2cc util.human.io: Factor out column width calculation
Kim Alvefur <zash@zash.se>
parents: 13367
diff changeset
179
10893
a256044c1d12 util.human.io: table: switch row function to simply returning prepared row string
Matthew Wild <mwild1@gmail.com>
parents: 10891
diff changeset
180 return function (row)
10896
c7a0eab27165 util.human.io: table: Fix title printing when columns use named keys
Matthew Wild <mwild1@gmail.com>
parents: 10894
diff changeset
181 local titles;
10894
d15a4284fdf8 util.human.io: table: Return title row when no row data passed
Matthew Wild <mwild1@gmail.com>
parents: 10893
diff changeset
182 if not row then
10896
c7a0eab27165 util.human.io: table: Fix title printing when columns use named keys
Matthew Wild <mwild1@gmail.com>
parents: 10894
diff changeset
183 titles, row = true, array.pluck(col_specs, "title", "");
10894
d15a4284fdf8 util.human.io: table: Return title row when no row data passed
Matthew Wild <mwild1@gmail.com>
parents: 10893
diff changeset
184 end
10893
a256044c1d12 util.human.io: table: switch row function to simply returning prepared row string
Matthew Wild <mwild1@gmail.com>
parents: 10891
diff changeset
185 local output = {};
10891
8d47858805c9 util.human.io: Add padleft, padright and a table printing function
Matthew Wild <mwild1@gmail.com>
parents: 10872
diff changeset
186 for i, column in ipairs(col_specs) do
8d47858805c9 util.human.io: Add padleft, padright and a table printing function
Matthew Wild <mwild1@gmail.com>
parents: 10872
diff changeset
187 local width = widths[i];
11892
e712133b4de1 util.human.io: Pass nil to cell mapper to signal missing value
Kim Alvefur <zash@zash.se>
parents: 10917
diff changeset
188 local v = row[not titles and column.key or i];
e712133b4de1 util.human.io: Pass nil to cell mapper to signal missing value
Kim Alvefur <zash@zash.se>
parents: 10917
diff changeset
189 if not titles and column.mapper then
13040
0cbe400ebab4 util.human.io: Pass the whole column definition to mapper function
Kim Alvefur <zash@zash.se>
parents: 13039
diff changeset
190 v = column.mapper(v, row, width, column);
11892
e712133b4de1 util.human.io: Pass nil to cell mapper to signal missing value
Kim Alvefur <zash@zash.se>
parents: 10917
diff changeset
191 end
e712133b4de1 util.human.io: Pass nil to cell mapper to signal missing value
Kim Alvefur <zash@zash.se>
parents: 10917
diff changeset
192 if v == nil then
11893
afef1e170de7 util.human.io: Support specifying column defaults in tables
Kim Alvefur <zash@zash.se>
parents: 11892
diff changeset
193 v = column.default or "";
11892
e712133b4de1 util.human.io: Pass nil to cell mapper to signal missing value
Kim Alvefur <zash@zash.se>
parents: 10917
diff changeset
194 else
e712133b4de1 util.human.io: Pass nil to cell mapper to signal missing value
Kim Alvefur <zash@zash.se>
parents: 10917
diff changeset
195 v = tostring(v);
e712133b4de1 util.human.io: Pass nil to cell mapper to signal missing value
Kim Alvefur <zash@zash.se>
parents: 10917
diff changeset
196 end
13937
cfe3e85e715f util.human.io: Support disabling column widths
Kim Alvefur <zash@zash.se>
parents: 13936
diff changeset
197 if width then
cfe3e85e715f util.human.io: Support disabling column widths
Kim Alvefur <zash@zash.se>
parents: 13936
diff changeset
198 if len(v) < width then
cfe3e85e715f util.human.io: Support disabling column widths
Kim Alvefur <zash@zash.se>
parents: 13936
diff changeset
199 if column.align == "right" then
cfe3e85e715f util.human.io: Support disabling column widths
Kim Alvefur <zash@zash.se>
parents: 13936
diff changeset
200 v = padleft(v, width);
cfe3e85e715f util.human.io: Support disabling column widths
Kim Alvefur <zash@zash.se>
parents: 13936
diff changeset
201 else
cfe3e85e715f util.human.io: Support disabling column widths
Kim Alvefur <zash@zash.se>
parents: 13936
diff changeset
202 v = padright(v, width);
cfe3e85e715f util.human.io: Support disabling column widths
Kim Alvefur <zash@zash.se>
parents: 13936
diff changeset
203 end
cfe3e85e715f util.human.io: Support disabling column widths
Kim Alvefur <zash@zash.se>
parents: 13936
diff changeset
204 elseif len(v) > width then
cfe3e85e715f util.human.io: Support disabling column widths
Kim Alvefur <zash@zash.se>
parents: 13936
diff changeset
205 v = (column.ellipsis or ellipsis)(v, width);
10891
8d47858805c9 util.human.io: Add padleft, padright and a table printing function
Matthew Wild <mwild1@gmail.com>
parents: 10872
diff changeset
206 end
8d47858805c9 util.human.io: Add padleft, padright and a table printing function
Matthew Wild <mwild1@gmail.com>
parents: 10872
diff changeset
207 end
10893
a256044c1d12 util.human.io: table: switch row function to simply returning prepared row string
Matthew Wild <mwild1@gmail.com>
parents: 10891
diff changeset
208 table.insert(output, v);
10891
8d47858805c9 util.human.io: Add padleft, padright and a table printing function
Matthew Wild <mwild1@gmail.com>
parents: 10872
diff changeset
209 end
10907
6af28c756752 util.human.io: Draw a separator between columns
Kim Alvefur <zash@zash.se>
parents: 10904
diff changeset
210 return table.concat(output, separator);
13048
946442df65d3 util.human.io: table: Return determined width as a second result
Matthew Wild <mwild1@gmail.com>
parents: 13047
diff changeset
211 end, max_width;
10891
8d47858805c9 util.human.io: Add padleft, padright and a table printing function
Matthew Wild <mwild1@gmail.com>
parents: 10872
diff changeset
212 end
8d47858805c9 util.human.io: Add padleft, padright and a table printing function
Matthew Wild <mwild1@gmail.com>
parents: 10872
diff changeset
213
13054
f4d7fe919969 util.human.io: Add parse_duration() method to parse a duration string
Matthew Wild <mwild1@gmail.com>
parents: 13051
diff changeset
214 local day = 86400;
f4d7fe919969 util.human.io: Add parse_duration() method to parse a duration string
Matthew Wild <mwild1@gmail.com>
parents: 13051
diff changeset
215 local multipliers = {
13367
82513890a1d8 util.human.io: Don't accept ambiguous durations by default
Matthew Wild <mwild1@gmail.com>
parents: 13210
diff changeset
216 d = day, w = day * 7, mon = 31 * day, y = 365.2425 * day;
82513890a1d8 util.human.io: Don't accept ambiguous durations by default
Matthew Wild <mwild1@gmail.com>
parents: 13210
diff changeset
217 s = 1, min = 60, h = 3600, ho = 3600
13054
f4d7fe919969 util.human.io: Add parse_duration() method to parse a duration string
Matthew Wild <mwild1@gmail.com>
parents: 13051
diff changeset
218 };
13367
82513890a1d8 util.human.io: Don't accept ambiguous durations by default
Matthew Wild <mwild1@gmail.com>
parents: 13210
diff changeset
219
13054
f4d7fe919969 util.human.io: Add parse_duration() method to parse a duration string
Matthew Wild <mwild1@gmail.com>
parents: 13051
diff changeset
220 local function parse_duration(duration_string)
13367
82513890a1d8 util.human.io: Don't accept ambiguous durations by default
Matthew Wild <mwild1@gmail.com>
parents: 13210
diff changeset
221 local n, m = duration_string:lower():match("(%d+)%s*([smhdwy]?[io]?n?)");
82513890a1d8 util.human.io: Don't accept ambiguous durations by default
Matthew Wild <mwild1@gmail.com>
parents: 13210
diff changeset
222 if not n or not multipliers[m] then return nil; end
82513890a1d8 util.human.io: Don't accept ambiguous durations by default
Matthew Wild <mwild1@gmail.com>
parents: 13210
diff changeset
223 return tonumber(n) * ( multipliers[m] or 1 );
82513890a1d8 util.human.io: Don't accept ambiguous durations by default
Matthew Wild <mwild1@gmail.com>
parents: 13210
diff changeset
224 end
82513890a1d8 util.human.io: Don't accept ambiguous durations by default
Matthew Wild <mwild1@gmail.com>
parents: 13210
diff changeset
225
82513890a1d8 util.human.io: Don't accept ambiguous durations by default
Matthew Wild <mwild1@gmail.com>
parents: 13210
diff changeset
226 local multipliers_lax = setmetatable({
82513890a1d8 util.human.io: Don't accept ambiguous durations by default
Matthew Wild <mwild1@gmail.com>
parents: 13210
diff changeset
227 m = multipliers.mon;
82513890a1d8 util.human.io: Don't accept ambiguous durations by default
Matthew Wild <mwild1@gmail.com>
parents: 13210
diff changeset
228 mo = multipliers.mon;
82513890a1d8 util.human.io: Don't accept ambiguous durations by default
Matthew Wild <mwild1@gmail.com>
parents: 13210
diff changeset
229 mi = multipliers.min;
82513890a1d8 util.human.io: Don't accept ambiguous durations by default
Matthew Wild <mwild1@gmail.com>
parents: 13210
diff changeset
230 }, { __index = multipliers });
82513890a1d8 util.human.io: Don't accept ambiguous durations by default
Matthew Wild <mwild1@gmail.com>
parents: 13210
diff changeset
231
82513890a1d8 util.human.io: Don't accept ambiguous durations by default
Matthew Wild <mwild1@gmail.com>
parents: 13210
diff changeset
232 local function parse_duration_lax(duration_string)
13199
278920294dfe util.human.io: Fix pattern in parse_duration() to cover all used letters
Kim Alvefur <zash@zash.se>
parents: 13068
diff changeset
233 local n, m = duration_string:lower():match("(%d+)%s*([smhdwy]?[io]?)");
13054
f4d7fe919969 util.human.io: Add parse_duration() method to parse a duration string
Matthew Wild <mwild1@gmail.com>
parents: 13051
diff changeset
234 if not n then return nil; end
13367
82513890a1d8 util.human.io: Don't accept ambiguous durations by default
Matthew Wild <mwild1@gmail.com>
parents: 13210
diff changeset
235 return tonumber(n) * ( multipliers_lax[m] or 1 );
13054
f4d7fe919969 util.human.io: Add parse_duration() method to parse a duration string
Matthew Wild <mwild1@gmail.com>
parents: 13051
diff changeset
236 end
f4d7fe919969 util.human.io: Add parse_duration() method to parse a duration string
Matthew Wild <mwild1@gmail.com>
parents: 13051
diff changeset
237
10870
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
238 return {
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
239 getchar = getchar;
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
240 getline = getline;
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
241 getpass = getpass;
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
242 show_yesno = show_yesno;
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
243 read_password = read_password;
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
244 show_prompt = show_prompt;
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
245 printf = printf;
10891
8d47858805c9 util.human.io: Add padleft, padright and a table printing function
Matthew Wild <mwild1@gmail.com>
parents: 10872
diff changeset
246 padleft = padleft;
8d47858805c9 util.human.io: Add padleft, padright and a table printing function
Matthew Wild <mwild1@gmail.com>
parents: 10872
diff changeset
247 padright = padright;
13044
5bd272095388 util.human.io: Add term_width() method to discover the terminal width
Matthew Wild <mwild1@gmail.com>
parents: 13040
diff changeset
248 term_width = term_width;
11894
57106c61d104 util.human.io: Factor out ellipsis function
Kim Alvefur <zash@zash.se>
parents: 11893
diff changeset
249 ellipsis = ellipsis;
10893
a256044c1d12 util.human.io: table: switch row function to simply returning prepared row string
Matthew Wild <mwild1@gmail.com>
parents: 10891
diff changeset
250 table = new_table;
13054
f4d7fe919969 util.human.io: Add parse_duration() method to parse a duration string
Matthew Wild <mwild1@gmail.com>
parents: 13051
diff changeset
251 parse_duration = parse_duration;
13367
82513890a1d8 util.human.io: Don't accept ambiguous durations by default
Matthew Wild <mwild1@gmail.com>
parents: 13210
diff changeset
252 parse_duration_lax = parse_duration_lax;
10870
3f1889608f3e util.human.io: New central place for UI helpers
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
253 };