aboutsummaryrefslogtreecommitdiff
path: root/docs/examples
diff options
context:
space:
mode:
authorThijs Schreijer <thijs@thijsschreijer.nl>2024-06-20 23:16:29 +0200
committerGitHub <noreply@github.com>2024-06-20 23:16:29 +0200
commitbb4fd73c317cc88beb5e58c1abf52138abed107f (patch)
tree35b774efc97d820a908424a5bc2452e0d6bf12a8 /docs/examples
parentc1a64c1b75f97cef97965b3bd9a941564a6270bd (diff)
downloadluasystem-0.4.0.tar.gz
luasystem-0.4.0.tar.bz2
luasystem-0.4.0.zip
Release v0.4.0 (#24)v0.4.0
Diffstat (limited to 'docs/examples')
-rw-r--r--docs/examples/compat.lua.html119
-rw-r--r--docs/examples/flag_debugging.lua.html87
-rw-r--r--docs/examples/password_input.lua.html139
-rw-r--r--docs/examples/read.lua.html150
-rw-r--r--docs/examples/readline.lua.html552
-rw-r--r--docs/examples/spinner.lua.html144
-rw-r--r--docs/examples/spiral_snake.lua.html152
-rw-r--r--docs/examples/terminalsize.lua.html117
8 files changed, 1460 insertions, 0 deletions
diff --git a/docs/examples/compat.lua.html b/docs/examples/compat.lua.html
new file mode 100644
index 0000000..a0abafe
--- /dev/null
+++ b/docs/examples/compat.lua.html
@@ -0,0 +1,119 @@
1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3<html>
4<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
5<head>
6 <title>Lua-System docs</title>
7 <link rel="stylesheet" href="../ldoc.css" type="text/css" />
8</head>
9<body>
10
11<div id="container">
12
13<div id="product">
14 <div id="product_logo"></div>
15 <div id="product_name"><big><b></b></big></div>
16 <div id="product_description"></div>
17</div> <!-- id="product" -->
18
19
20<div id="main">
21
22
23<!-- Menu -->
24
25<div id="navigation">
26<br/>
27<h1>Lua-System</h1>
28
29
30<ul>
31 <li><a href="../index.html">Index</a></li>
32</ul>
33
34
35
36<h2>Examples</h2>
37<ul class="nowrap">
38 <li><strong>compat.lua</strong></li>
39 <li><a href="../examples/flag_debugging.lua.html">flag_debugging.lua</a></li>
40 <li><a href="../examples/password_input.lua.html">password_input.lua</a></li>
41 <li><a href="../examples/read.lua.html">read.lua</a></li>
42 <li><a href="../examples/readline.lua.html">readline.lua</a></li>
43 <li><a href="../examples/spinner.lua.html">spinner.lua</a></li>
44 <li><a href="../examples/spiral_snake.lua.html">spiral_snake.lua</a></li>
45 <li><a href="../examples/terminalsize.lua.html">terminalsize.lua</a></li>
46</ul>
47<h2>Modules</h2>
48<ul class="nowrap">
49 <li><a href="../modules/system.html">system</a></li>
50</ul>
51<h2>Classes</h2>
52<ul class="nowrap">
53 <li><a href="../classes/bitflags.html">bitflags</a></li>
54</ul>
55<h2>Topics</h2>
56<ul class="">
57 <li><a href="../topics/01-introduction.md.html">1. Introduction</a></li>
58 <li><a href="../topics/02-development.md.html">2. Development</a></li>
59 <li><a href="../topics/03-terminal.md.html">3. Terminal functionality</a></li>
60 <li><a href="../topics/CHANGELOG.md.html">CHANGELOG</a></li>
61 <li><a href="../topics/LICENSE.md.html">MIT License</a></li>
62</ul>
63
64</div>
65
66<div id="content">
67
68 <h2>compat.lua</h2>
69<pre>
70<span class="comment">-- This example shows how to remove platform differences to create a
71</span><span class="comment">-- cross-platform level playing field.
72</span>
73<span class="keyword">local</span> sys = <span class="global">require</span> <span class="string">"system"</span>
74
75
76
77<span class="keyword">if</span> sys.windows <span class="keyword">then</span>
78 <span class="comment">-- Windows holds multiple copies of environment variables, to ensure <code>getenv</code>
79</span> <span class="comment">-- returns what <code>setenv</code> sets we need to use the <a href="../modules/system.html#getenv">system.getenv</a> instead of
80</span> <span class="comment">-- <a href="https://www.lua.org/manual/5.4/manual.html#pdf-os.getenv">os.getenv</a>.
81</span> <span class="global">os</span>.getenv = sys.getenv <span class="comment">-- luacheck: ignore
82</span>
83 <span class="comment">-- Set console output to UTF-8 encoding.
84</span> sys.<span class="function-name">setconsoleoutputcp</span>(sys.CODEPAGE_UTF8)
85
86 <span class="comment">-- Set up the terminal to handle ANSI escape sequences on Windows.
87</span> <span class="keyword">if</span> sys.<span class="function-name">isatty</span>(<span class="global">io</span>.stdout) <span class="keyword">then</span>
88 sys.<span class="function-name">setconsoleflags</span>(<span class="global">io</span>.stdout, sys.<span class="function-name">getconsoleflags</span>(<span class="global">io</span>.stdout) + sys.COF_VIRTUAL_TERMINAL_PROCESSING)
89 <span class="keyword">end</span>
90 <span class="keyword">if</span> sys.<span class="function-name">isatty</span>(<span class="global">io</span>.stderr) <span class="keyword">then</span>
91 sys.<span class="function-name">setconsoleflags</span>(<span class="global">io</span>.stderr, sys.<span class="function-name">getconsoleflags</span>(<span class="global">io</span>.stderr) + sys.COF_VIRTUAL_TERMINAL_PROCESSING)
92 <span class="keyword">end</span>
93 <span class="keyword">if</span> sys.<span class="function-name">isatty</span>(<span class="global">io</span>.stdin) <span class="keyword">then</span>
94 sys.<span class="function-name">setconsoleflags</span>(<span class="global">io</span>.stdin, sys.<span class="function-name">getconsoleflags</span>(<span class="global">io</span>.stdout) + sys.ENABLE_VIRTUAL_TERMINAL_INPUT)
95 <span class="keyword">end</span>
96
97
98<span class="keyword">else</span>
99 <span class="comment">-- On Posix, one can set a variable to an empty string, but on Windows, this
100</span> <span class="comment">-- will remove the variable from the environment. To make this consistent
101</span> <span class="comment">-- across platforms, we will remove the variable from the environment if the
102</span> <span class="comment">-- value is an empty string.
103</span> <span class="keyword">local</span> old_setenv = sys.setenv
104 <span class="keyword">function</span> sys.<span class="function-name">setenv</span>(name, value)
105 <span class="keyword">if</span> value == <span class="string">""</span> <span class="keyword">then</span> value = <span class="keyword">nil</span> <span class="keyword">end</span>
106 <span class="keyword">return</span> <span class="function-name">old_setenv</span>(name, value)
107 <span class="keyword">end</span>
108<span class="keyword">end</span></pre>
109
110
111</div> <!-- id="content" -->
112</div> <!-- id="main" -->
113<div id="about">
114<i>generated by <a href="http://github.com/lunarmodules/LDoc">LDoc 1.5.0</a></i>
115<i style="float:right;">Last updated 2024-06-20 23:11:37 </i>
116</div> <!-- id="about" -->
117</div> <!-- id="container" -->
118</body>
119</html>
diff --git a/docs/examples/flag_debugging.lua.html b/docs/examples/flag_debugging.lua.html
new file mode 100644
index 0000000..38f506a
--- /dev/null
+++ b/docs/examples/flag_debugging.lua.html
@@ -0,0 +1,87 @@
1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3<html>
4<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
5<head>
6 <title>Lua-System docs</title>
7 <link rel="stylesheet" href="../ldoc.css" type="text/css" />
8</head>
9<body>
10
11<div id="container">
12
13<div id="product">
14 <div id="product_logo"></div>
15 <div id="product_name"><big><b></b></big></div>
16 <div id="product_description"></div>
17</div> <!-- id="product" -->
18
19
20<div id="main">
21
22
23<!-- Menu -->
24
25<div id="navigation">
26<br/>
27<h1>Lua-System</h1>
28
29
30<ul>
31 <li><a href="../index.html">Index</a></li>
32</ul>
33
34
35
36<h2>Examples</h2>
37<ul class="nowrap">
38 <li><a href="../examples/compat.lua.html">compat.lua</a></li>
39 <li><strong>flag_debugging.lua</strong></li>
40 <li><a href="../examples/password_input.lua.html">password_input.lua</a></li>
41 <li><a href="../examples/read.lua.html">read.lua</a></li>
42 <li><a href="../examples/readline.lua.html">readline.lua</a></li>
43 <li><a href="../examples/spinner.lua.html">spinner.lua</a></li>
44 <li><a href="../examples/spiral_snake.lua.html">spiral_snake.lua</a></li>
45 <li><a href="../examples/terminalsize.lua.html">terminalsize.lua</a></li>
46</ul>
47<h2>Modules</h2>
48<ul class="nowrap">
49 <li><a href="../modules/system.html">system</a></li>
50</ul>
51<h2>Classes</h2>
52<ul class="nowrap">
53 <li><a href="../classes/bitflags.html">bitflags</a></li>
54</ul>
55<h2>Topics</h2>
56<ul class="">
57 <li><a href="../topics/01-introduction.md.html">1. Introduction</a></li>
58 <li><a href="../topics/02-development.md.html">2. Development</a></li>
59 <li><a href="../topics/03-terminal.md.html">3. Terminal functionality</a></li>
60 <li><a href="../topics/CHANGELOG.md.html">CHANGELOG</a></li>
61 <li><a href="../topics/LICENSE.md.html">MIT License</a></li>
62</ul>
63
64</div>
65
66<div id="content">
67
68 <h2>flag_debugging.lua</h2>
69<pre>
70<span class="keyword">local</span> sys = <span class="global">require</span> <span class="string">"system"</span>
71
72<span class="comment">-- Print the Windows Console flags for stdin
73</span>sys.<span class="function-name">listconsoleflags</span>(<span class="global">io</span>.stdin)
74
75<span class="comment">-- Print the Posix termios flags for stdin
76</span>sys.<span class="function-name">listtermflags</span>(<span class="global">io</span>.stdin)</pre>
77
78
79</div> <!-- id="content" -->
80</div> <!-- id="main" -->
81<div id="about">
82<i>generated by <a href="http://github.com/lunarmodules/LDoc">LDoc 1.5.0</a></i>
83<i style="float:right;">Last updated 2024-06-20 23:11:37 </i>
84</div> <!-- id="about" -->
85</div> <!-- id="container" -->
86</body>
87</html>
diff --git a/docs/examples/password_input.lua.html b/docs/examples/password_input.lua.html
new file mode 100644
index 0000000..4234fbb
--- /dev/null
+++ b/docs/examples/password_input.lua.html
@@ -0,0 +1,139 @@
1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3<html>
4<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
5<head>
6 <title>Lua-System docs</title>
7 <link rel="stylesheet" href="../ldoc.css" type="text/css" />
8</head>
9<body>
10
11<div id="container">
12
13<div id="product">
14 <div id="product_logo"></div>
15 <div id="product_name"><big><b></b></big></div>
16 <div id="product_description"></div>
17</div> <!-- id="product" -->
18
19
20<div id="main">
21
22
23<!-- Menu -->
24
25<div id="navigation">
26<br/>
27<h1>Lua-System</h1>
28
29
30<ul>
31 <li><a href="../index.html">Index</a></li>
32</ul>
33
34
35
36<h2>Examples</h2>
37<ul class="nowrap">
38 <li><a href="../examples/compat.lua.html">compat.lua</a></li>
39 <li><a href="../examples/flag_debugging.lua.html">flag_debugging.lua</a></li>
40 <li><strong>password_input.lua</strong></li>
41 <li><a href="../examples/read.lua.html">read.lua</a></li>
42 <li><a href="../examples/readline.lua.html">readline.lua</a></li>
43 <li><a href="../examples/spinner.lua.html">spinner.lua</a></li>
44 <li><a href="../examples/spiral_snake.lua.html">spiral_snake.lua</a></li>
45 <li><a href="../examples/terminalsize.lua.html">terminalsize.lua</a></li>
46</ul>
47<h2>Modules</h2>
48<ul class="nowrap">
49 <li><a href="../modules/system.html">system</a></li>
50</ul>
51<h2>Classes</h2>
52<ul class="nowrap">
53 <li><a href="../classes/bitflags.html">bitflags</a></li>
54</ul>
55<h2>Topics</h2>
56<ul class="">
57 <li><a href="../topics/01-introduction.md.html">1. Introduction</a></li>
58 <li><a href="../topics/02-development.md.html">2. Development</a></li>
59 <li><a href="../topics/03-terminal.md.html">3. Terminal functionality</a></li>
60 <li><a href="../topics/CHANGELOG.md.html">CHANGELOG</a></li>
61 <li><a href="../topics/LICENSE.md.html">MIT License</a></li>
62</ul>
63
64</div>
65
66<div id="content">
67
68 <h2>password_input.lua</h2>
69<pre>
70<span class="keyword">local</span> sys = <span class="global">require</span> <span class="string">"system"</span>
71
72<span class="global">print</span> <span class="string">[[
73
74This example shows how to disable the "echo" of characters read to the console,
75useful for reading secrets from the user.
76
77]]</span>
78
79<span class="comment">--- Function to read from stdin without echoing the input (for secrets etc).
80</span><span class="comment">-- It will (in a platform agnostic way) disable echo on the terminal, read the
81</span><span class="comment">-- input, and then re-enable echo.
82</span><span class="comment">-- @param ... Arguments to pass to <code>io.stdin:read()</code>
83</span><span class="comment">-- @return the results of <code>io.stdin:read(...)</code>
84</span><span class="keyword">local</span> <span class="keyword">function</span> <span class="function-name">read_secret</span>(...)
85 <span class="keyword">local</span> w_oldflags, p_oldflags
86
87 <span class="keyword">if</span> sys.<span class="function-name">isatty</span>(<span class="global">io</span>.stdin) <span class="keyword">then</span>
88 <span class="comment">-- backup settings, configure echo flags
89</span> w_oldflags = sys.<span class="function-name">getconsoleflags</span>(<span class="global">io</span>.stdin)
90 p_oldflags = sys.<span class="function-name">tcgetattr</span>(<span class="global">io</span>.stdin)
91 <span class="comment">-- set echo off to not show password on screen
92</span> <span class="global">assert</span>(sys.<span class="function-name">setconsoleflags</span>(<span class="global">io</span>.stdin, w_oldflags - sys.CIF_ECHO_INPUT))
93 <span class="global">assert</span>(sys.<span class="function-name">tcsetattr</span>(<span class="global">io</span>.stdin, sys.TCSANOW, { lflag = p_oldflags.lflag - sys.L_ECHO }))
94 <span class="keyword">end</span>
95
96 <span class="keyword">local</span> secret, err = <span class="global">io</span>.stdin:<span class="function-name">read</span>(...)
97
98 <span class="comment">-- restore settings
99</span> <span class="keyword">if</span> sys.<span class="function-name">isatty</span>(<span class="global">io</span>.stdin) <span class="keyword">then</span>
100 <span class="global">io</span>.stdout:<span class="function-name">write</span>(<span class="string">"\n"</span>) <span class="comment">-- Add newline after reading the password
101</span> sys.<span class="function-name">setconsoleflags</span>(<span class="global">io</span>.stdin, w_oldflags)
102 sys.<span class="function-name">tcsetattr</span>(<span class="global">io</span>.stdin, sys.TCSANOW, p_oldflags)
103 <span class="keyword">end</span>
104
105 <span class="keyword">return</span> secret, err
106<span class="keyword">end</span>
107
108
109
110<span class="comment">-- Get username
111</span><span class="global">io</span>.<span class="function-name">write</span>(<span class="string">"Username: "</span>)
112<span class="keyword">local</span> username = <span class="global">io</span>.stdin:<span class="function-name">read</span>(<span class="string">"*l"</span>)
113
114<span class="comment">-- Get the secret
115</span><span class="global">io</span>.<span class="function-name">write</span>(<span class="string">"Password: "</span>)
116<span class="keyword">local</span> password = <span class="function-name">read_secret</span>(<span class="string">"*l"</span>)
117
118<span class="comment">-- Get domainname
119</span><span class="global">io</span>.<span class="function-name">write</span>(<span class="string">"Domain : "</span>)
120<span class="keyword">local</span> domain = <span class="global">io</span>.stdin:<span class="function-name">read</span>(<span class="string">"*l"</span>)
121
122
123<span class="comment">-- Print the results
124</span><span class="global">print</span>(<span class="string">""</span>)
125<span class="global">print</span>(<span class="string">"Here's what we got:"</span>)
126<span class="global">print</span>(<span class="string">" username: "</span> .. username)
127<span class="global">print</span>(<span class="string">" password: "</span> .. password)
128<span class="global">print</span>(<span class="string">" domain : "</span> .. domain)</pre>
129
130
131</div> <!-- id="content" -->
132</div> <!-- id="main" -->
133<div id="about">
134<i>generated by <a href="http://github.com/lunarmodules/LDoc">LDoc 1.5.0</a></i>
135<i style="float:right;">Last updated 2024-06-20 23:11:37 </i>
136</div> <!-- id="about" -->
137</div> <!-- id="container" -->
138</body>
139</html>
diff --git a/docs/examples/read.lua.html b/docs/examples/read.lua.html
new file mode 100644
index 0000000..c7697d3
--- /dev/null
+++ b/docs/examples/read.lua.html
@@ -0,0 +1,150 @@
1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3<html>
4<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
5<head>
6 <title>Lua-System docs</title>
7 <link rel="stylesheet" href="../ldoc.css" type="text/css" />
8</head>
9<body>
10
11<div id="container">
12
13<div id="product">
14 <div id="product_logo"></div>
15 <div id="product_name"><big><b></b></big></div>
16 <div id="product_description"></div>
17</div> <!-- id="product" -->
18
19
20<div id="main">
21
22
23<!-- Menu -->
24
25<div id="navigation">
26<br/>
27<h1>Lua-System</h1>
28
29
30<ul>
31 <li><a href="../index.html">Index</a></li>
32</ul>
33
34
35
36<h2>Examples</h2>
37<ul class="nowrap">
38 <li><a href="../examples/compat.lua.html">compat.lua</a></li>
39 <li><a href="../examples/flag_debugging.lua.html">flag_debugging.lua</a></li>
40 <li><a href="../examples/password_input.lua.html">password_input.lua</a></li>
41 <li><strong>read.lua</strong></li>
42 <li><a href="../examples/readline.lua.html">readline.lua</a></li>
43 <li><a href="../examples/spinner.lua.html">spinner.lua</a></li>
44 <li><a href="../examples/spiral_snake.lua.html">spiral_snake.lua</a></li>
45 <li><a href="../examples/terminalsize.lua.html">terminalsize.lua</a></li>
46</ul>
47<h2>Modules</h2>
48<ul class="nowrap">
49 <li><a href="../modules/system.html">system</a></li>
50</ul>
51<h2>Classes</h2>
52<ul class="nowrap">
53 <li><a href="../classes/bitflags.html">bitflags</a></li>
54</ul>
55<h2>Topics</h2>
56<ul class="">
57 <li><a href="../topics/01-introduction.md.html">1. Introduction</a></li>
58 <li><a href="../topics/02-development.md.html">2. Development</a></li>
59 <li><a href="../topics/03-terminal.md.html">3. Terminal functionality</a></li>
60 <li><a href="../topics/CHANGELOG.md.html">CHANGELOG</a></li>
61 <li><a href="../topics/LICENSE.md.html">MIT License</a></li>
62</ul>
63
64</div>
65
66<div id="content">
67
68 <h2>read.lua</h2>
69<pre>
70<span class="keyword">local</span> sys = <span class="global">require</span> <span class="string">"system"</span>
71
72<span class="global">print</span> <span class="string">[[
73
74This example shows how to do a non-blocking read from the cli.
75
76]]</span>
77
78<span class="comment">-- setup Windows console to handle ANSI processing
79</span><span class="keyword">local</span> of_in = sys.<span class="function-name">getconsoleflags</span>(<span class="global">io</span>.stdin)
80<span class="keyword">local</span> of_out = sys.<span class="function-name">getconsoleflags</span>(<span class="global">io</span>.stdout)
81sys.<span class="function-name">setconsoleflags</span>(<span class="global">io</span>.stdout, sys.<span class="function-name">getconsoleflags</span>(<span class="global">io</span>.stdout) + sys.COF_VIRTUAL_TERMINAL_PROCESSING)
82sys.<span class="function-name">setconsoleflags</span>(<span class="global">io</span>.stdin, sys.<span class="function-name">getconsoleflags</span>(<span class="global">io</span>.stdin) + sys.CIF_VIRTUAL_TERMINAL_INPUT)
83
84<span class="comment">-- setup Posix terminal to use non-blocking mode, and disable line-mode
85</span><span class="keyword">local</span> of_attr = sys.<span class="function-name">tcgetattr</span>(<span class="global">io</span>.stdin)
86<span class="keyword">local</span> of_block = sys.<span class="function-name">getnonblock</span>(<span class="global">io</span>.stdin)
87sys.<span class="function-name">setnonblock</span>(<span class="global">io</span>.stdin, <span class="keyword">true</span>)
88sys.<span class="function-name">tcsetattr</span>(<span class="global">io</span>.stdin, sys.TCSANOW, {
89 lflag = of_attr.lflag - sys.L_ICANON - sys.L_ECHO, <span class="comment">-- disable canonical mode and echo
90</span>})
91
92<span class="comment">-- cursor sequences
93</span><span class="keyword">local</span> get_cursor_pos = <span class="string">"\27[6n"</span>
94
95
96
97<span class="global">print</span>(<span class="string">"Press a key, or 'A' to get cursor position, 'ESC' to exit"</span>)
98<span class="keyword">while</span> <span class="keyword">true</span> <span class="keyword">do</span>
99 <span class="keyword">local</span> key, keytype
100
101 <span class="comment">-- wait for a key
102</span> <span class="keyword">while</span> <span class="keyword">not</span> key <span class="keyword">do</span>
103 key, keytype = sys.<span class="function-name">readansi</span>(<span class="global">math</span>.huge)
104 <span class="keyword">end</span>
105
106 <span class="keyword">if</span> key == <span class="string">"A"</span> <span class="keyword">then</span> <span class="global">io</span>.<span class="function-name">write</span>(get_cursor_pos); <span class="global">io</span>.<span class="function-name">flush</span>() <span class="keyword">end</span>
107
108 <span class="comment">-- check if we got a key or ANSI sequence
109</span> <span class="keyword">if</span> keytype == <span class="string">"char"</span> <span class="keyword">then</span>
110 <span class="comment">-- just a key
111</span> <span class="keyword">local</span> b = key:<span class="function-name">byte</span>()
112 <span class="keyword">if</span> b &lt; <span class="number">32</span> <span class="keyword">then</span>
113 key = <span class="string">"."</span> <span class="comment">-- replace control characters with a simple "." to not mess up the screen
114</span> <span class="keyword">end</span>
115
116 <span class="global">print</span>(<span class="string">"you pressed: "</span> .. key .. <span class="string">" ("</span> .. b .. <span class="string">")"</span>)
117 <span class="keyword">if</span> b == <span class="number">27</span> <span class="keyword">then</span>
118 <span class="global">print</span>(<span class="string">"Escape pressed, exiting"</span>)
119 <span class="keyword">break</span>
120 <span class="keyword">end</span>
121
122 <span class="keyword">elseif</span> keytype == <span class="string">"ansi"</span> <span class="keyword">then</span>
123 <span class="comment">-- we got an ANSI sequence
124</span> <span class="keyword">local</span> seq = { key:<span class="function-name">byte</span>(<span class="number">1</span>, #key) }
125 <span class="global">print</span>(<span class="string">"ANSI sequence received: "</span> .. key:<span class="function-name">sub</span>(<span class="number">2</span>,-<span class="number">1</span>), <span class="string">"(bytes: "</span> .. <span class="global">table</span>.<span class="function-name">concat</span>(seq, <span class="string">", "</span>)..<span class="string">")"</span>)
126
127 <span class="keyword">else</span>
128 <span class="global">print</span>(<span class="string">"unknown key type received: "</span> .. <span class="global">tostring</span>(keytype))
129 <span class="keyword">end</span>
130<span class="keyword">end</span>
131
132
133
134<span class="comment">-- Clean up afterwards
135</span>sys.<span class="function-name">setnonblock</span>(<span class="global">io</span>.stdin, <span class="keyword">false</span>)
136sys.<span class="function-name">setconsoleflags</span>(<span class="global">io</span>.stdout, of_out)
137sys.<span class="function-name">setconsoleflags</span>(<span class="global">io</span>.stdin, of_in)
138sys.<span class="function-name">tcsetattr</span>(<span class="global">io</span>.stdin, sys.TCSANOW, of_attr)
139sys.<span class="function-name">setnonblock</span>(<span class="global">io</span>.stdin, of_block)</pre>
140
141
142</div> <!-- id="content" -->
143</div> <!-- id="main" -->
144<div id="about">
145<i>generated by <a href="http://github.com/lunarmodules/LDoc">LDoc 1.5.0</a></i>
146<i style="float:right;">Last updated 2024-06-20 23:11:37 </i>
147</div> <!-- id="about" -->
148</div> <!-- id="container" -->
149</body>
150</html>
diff --git a/docs/examples/readline.lua.html b/docs/examples/readline.lua.html
new file mode 100644
index 0000000..7895a81
--- /dev/null
+++ b/docs/examples/readline.lua.html
@@ -0,0 +1,552 @@
1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3<html>
4<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
5<head>
6 <title>Lua-System docs</title>
7 <link rel="stylesheet" href="../ldoc.css" type="text/css" />
8</head>
9<body>
10
11<div id="container">
12
13<div id="product">
14 <div id="product_logo"></div>
15 <div id="product_name"><big><b></b></big></div>
16 <div id="product_description"></div>
17</div> <!-- id="product" -->
18
19
20<div id="main">
21
22
23<!-- Menu -->
24
25<div id="navigation">
26<br/>
27<h1>Lua-System</h1>
28
29
30<ul>
31 <li><a href="../index.html">Index</a></li>
32</ul>
33
34
35
36<h2>Examples</h2>
37<ul class="nowrap">
38 <li><a href="../examples/compat.lua.html">compat.lua</a></li>
39 <li><a href="../examples/flag_debugging.lua.html">flag_debugging.lua</a></li>
40 <li><a href="../examples/password_input.lua.html">password_input.lua</a></li>
41 <li><a href="../examples/read.lua.html">read.lua</a></li>
42 <li><strong>readline.lua</strong></li>
43 <li><a href="../examples/spinner.lua.html">spinner.lua</a></li>
44 <li><a href="../examples/spiral_snake.lua.html">spiral_snake.lua</a></li>
45 <li><a href="../examples/terminalsize.lua.html">terminalsize.lua</a></li>
46</ul>
47<h2>Modules</h2>
48<ul class="nowrap">
49 <li><a href="../modules/system.html">system</a></li>
50</ul>
51<h2>Classes</h2>
52<ul class="nowrap">
53 <li><a href="../classes/bitflags.html">bitflags</a></li>
54</ul>
55<h2>Topics</h2>
56<ul class="">
57 <li><a href="../topics/01-introduction.md.html">1. Introduction</a></li>
58 <li><a href="../topics/02-development.md.html">2. Development</a></li>
59 <li><a href="../topics/03-terminal.md.html">3. Terminal functionality</a></li>
60 <li><a href="../topics/CHANGELOG.md.html">CHANGELOG</a></li>
61 <li><a href="../topics/LICENSE.md.html">MIT License</a></li>
62</ul>
63
64</div>
65
66<div id="content">
67
68 <h2>readline.lua</h2>
69<pre>
70<span class="comment">--- An example class for reading a line of input from the user in a non-blocking way.
71</span><span class="comment">-- It uses ANSI escape sequences to move the cursor and handle input.
72</span><span class="comment">-- It can be used to read a line of input from the user, with a prompt.
73</span><span class="comment">-- It can handle double-width UTF-8 characters.
74</span><span class="comment">-- It can be used asynchroneously if <a href="../modules/system.html#sleep">system.sleep</a> is patched to yield to a coroutine scheduler.
75</span>
76<span class="keyword">local</span> sys = <span class="global">require</span>(<span class="string">"system"</span>)
77
78
79<span class="comment">-- Mapping of key-sequences to key-names
80</span><span class="keyword">local</span> key_names = {
81 [<span class="string">"\27[C"</span>] = <span class="string">"right"</span>,
82 [<span class="string">"\27[D"</span>] = <span class="string">"left"</span>,
83 [<span class="string">"\127"</span>] = <span class="string">"backspace"</span>,
84 [<span class="string">"\27[3~"</span>] = <span class="string">"delete"</span>,
85 [<span class="string">"\27[H"</span>] = <span class="string">"home"</span>,
86 [<span class="string">"\27[F"</span>] = <span class="string">"end"</span>,
87 [<span class="string">"\27"</span>] = <span class="string">"escape"</span>,
88 [<span class="string">"\9"</span>] = <span class="string">"tab"</span>,
89 [<span class="string">"\27[Z"</span>] = <span class="string">"shift-tab"</span>,
90}
91
92<span class="keyword">if</span> sys.windows <span class="keyword">then</span>
93 key_names[<span class="string">"\13"</span>] = <span class="string">"enter"</span>
94<span class="keyword">else</span>
95 key_names[<span class="string">"\10"</span>] = <span class="string">"enter"</span>
96<span class="keyword">end</span>
97
98
99<span class="comment">-- Mapping of key-names to key-sequences
100</span><span class="keyword">local</span> key_sequences = {}
101<span class="keyword">for</span> k, v <span class="keyword">in</span> <span class="global">pairs</span>(key_names) <span class="keyword">do</span>
102 key_sequences[v] = k
103<span class="keyword">end</span>
104
105
106<span class="comment">-- bell character
107</span><span class="keyword">local</span> <span class="keyword">function</span> <span class="function-name">bell</span>()
108 <span class="global">io</span>.<span class="function-name">write</span>(<span class="string">"\7"</span>)
109 <span class="global">io</span>.<span class="function-name">flush</span>()
110<span class="keyword">end</span>
111
112
113<span class="comment">-- generate string to move cursor horizontally
114</span><span class="comment">-- positive goes right, negative goes left
115</span><span class="keyword">local</span> <span class="keyword">function</span> <span class="function-name">cursor_move_horiz</span>(n)
116 <span class="keyword">if</span> n == <span class="number">0</span> <span class="keyword">then</span>
117 <span class="keyword">return</span> <span class="string">""</span>
118 <span class="keyword">end</span>
119 <span class="keyword">return</span> <span class="string">"\27["</span> .. (n &gt; <span class="number">0</span> <span class="keyword">and</span> n <span class="keyword">or</span> -n) .. (n &gt; <span class="number">0</span> <span class="keyword">and</span> <span class="string">"C"</span> <span class="keyword">or</span> <span class="string">"D"</span>)
120<span class="keyword">end</span>
121
122
123<span class="comment">-- -- generate string to move cursor vertically
124</span><span class="comment">-- -- positive goes down, negative goes up
125</span><span class="comment">-- local function cursor_move_vert(n)
126</span><span class="comment">-- if n == 0 then
127</span><span class="comment">-- return ""
128</span><span class="comment">-- end
129</span><span class="comment">-- return "\27[" .. (n &gt; 0 and n or -n) .. (n &gt; 0 and "B" or "A")
130</span><span class="comment">-- end
131</span>
132
133<span class="comment">-- -- log to the line above the current line
134</span><span class="comment">-- local function log(...)
135</span><span class="comment">-- local arg = { n = select("#", ...), ...}
136</span><span class="comment">-- for i = 1, arg.n do
137</span><span class="comment">-- arg[i] = tostring(arg[i])
138</span><span class="comment">-- end
139</span><span class="comment">-- arg = " " .. table.concat(arg, " ") .. " "
140</span>
141<span class="comment">-- io.write(cursor_move_vert(-1), arg, cursor_move_vert(1), cursor_move_horiz(-#arg))
142</span><span class="comment">-- end
143</span>
144
145<span class="comment">-- UTF8 character size in bytes
146</span><span class="comment">-- @tparam number b the byte value of the first byte of a UTF8 character
147</span><span class="keyword">local</span> <span class="keyword">function</span> <span class="function-name">utf8size</span>(b)
148 <span class="keyword">return</span> b &lt; <span class="number">128</span> <span class="keyword">and</span> <span class="number">1</span> <span class="keyword">or</span> b &lt; <span class="number">224</span> <span class="keyword">and</span> <span class="number">2</span> <span class="keyword">or</span> b &lt; <span class="number">240</span> <span class="keyword">and</span> <span class="number">3</span> <span class="keyword">or</span> b &lt; <span class="number">248</span> <span class="keyword">and</span> <span class="number">4</span>
149<span class="keyword">end</span>
150
151
152
153<span class="keyword">local</span> utf8parse <span class="keyword">do</span>
154 <span class="keyword">local</span> utf8_value_mt = {
155 __tostring = <span class="keyword">function</span>(self)
156 <span class="keyword">return</span> <span class="global">table</span>.<span class="function-name">concat</span>(self, <span class="string">""</span>)
157 <span class="keyword">end</span>,
158 }
159
160 <span class="comment">-- Parses a UTF8 string into list of individual characters.
161</span> <span class="comment">-- key 'chars' gets the length in UTF8 characters, whilst # returns the length
162</span> <span class="comment">-- for display (to handle double-width UTF8 chars).
163</span> <span class="comment">-- in the list the double-width characters are followed by an empty string.
164</span> <span class="comment">-- @tparam string s the UTF8 string to parse
165</span> <span class="comment">-- @treturn table the list of characters
166</span> <span class="keyword">function</span> <span class="function-name">utf8parse</span>(s)
167 <span class="keyword">local</span> t = <span class="global">setmetatable</span>({ chars = <span class="number">0</span> }, utf8_value_mt)
168 <span class="keyword">local</span> i = <span class="number">1</span>
169 <span class="keyword">while</span> i &lt;= #s <span class="keyword">do</span>
170 <span class="keyword">local</span> b = s:<span class="function-name">byte</span>(i)
171 <span class="keyword">local</span> w = <span class="function-name">utf8size</span>(b)
172 <span class="keyword">local</span> char = s:<span class="function-name">sub</span>(i, i + w - <span class="number">1</span>)
173 t[#t + <span class="number">1</span>] = char
174 t.chars = t.chars + <span class="number">1</span>
175 <span class="keyword">if</span> sys.<span class="function-name">utf8cwidth</span>(char) == <span class="number">2</span> <span class="keyword">then</span>
176 <span class="comment">-- double width character, add empty string to keep the length of the
177</span> <span class="comment">-- list the same as the character width on screen
178</span> t[#t + <span class="number">1</span>] = <span class="string">""</span>
179 <span class="keyword">end</span>
180 i = i + w
181 <span class="keyword">end</span>
182 <span class="keyword">return</span> t
183 <span class="keyword">end</span>
184<span class="keyword">end</span>
185
186
187
188<span class="comment">-- inline tests for utf8parse
189</span><span class="comment">-- do
190</span><span class="comment">-- local t = utf8parse("a你b好c")
191</span><span class="comment">-- assert(t[1] == "a")
192</span><span class="comment">-- assert(t[2] == "ä½ ") -- double width
193</span><span class="comment">-- assert(t[3] == "")
194</span><span class="comment">-- assert(t[4] == "b")
195</span><span class="comment">-- assert(t[5] == "好") -- double width
196</span><span class="comment">-- assert(t[6] == "")
197</span><span class="comment">-- assert(t[7] == "c")
198</span><span class="comment">-- assert(#t == 7) -- size as displayed
199</span><span class="comment">-- end
200</span>
201
202
203<span class="comment">-- readline class
204</span>
205<span class="keyword">local</span> readline = {}
206readline.__index = readline
207
208
209<span class="comment">--- Create a new readline object.
210</span><span class="comment">-- @tparam table opts the options for the readline object
211</span><span class="comment">-- @tparam[opt=""] string opts.prompt the prompt to display
212</span><span class="comment">-- @tparam[opt=80] number opts.max_length the maximum length of the input (in characters, not bytes)
213</span><span class="comment">-- @tparam[opt=""] string opts.value the default value
214</span><span class="comment">-- @tparam[opt=<code>#value</code>] number opts.position of the cursor in the input
215</span><span class="comment">-- @tparam[opt={"\10"/"\13"}] table opts.exit_keys an array of keys that will cause the readline to exit
216</span><span class="comment">-- @treturn readline the new readline object
217</span><span class="keyword">function</span> readline.<span class="function-name">new</span>(opts)
218 <span class="keyword">local</span> value = <span class="function-name">utf8parse</span>(opts.value <span class="keyword">or</span> <span class="string">""</span>)
219 <span class="keyword">local</span> prompt = <span class="function-name">utf8parse</span>(opts.prompt <span class="keyword">or</span> <span class="string">""</span>)
220 <span class="keyword">local</span> pos = <span class="global">math</span>.<span class="function-name">floor</span>(opts.position <span class="keyword">or</span> (#value + <span class="number">1</span>))
221 pos = <span class="global">math</span>.<span class="function-name">max</span>(<span class="global">math</span>.<span class="function-name">min</span>(pos, (#value + <span class="number">1</span>)), <span class="number">1</span>)
222 <span class="keyword">local</span> len = <span class="global">math</span>.<span class="function-name">floor</span>(opts.max_length <span class="keyword">or</span> <span class="number">80</span>)
223 <span class="keyword">if</span> len &lt; <span class="number">1</span> <span class="keyword">then</span>
224 <span class="global">error</span>(<span class="string">"max_length must be at least 1"</span>, <span class="number">2</span>)
225 <span class="keyword">end</span>
226
227 <span class="keyword">if</span> value.chars &gt; len <span class="keyword">then</span>
228 <span class="global">error</span>(<span class="string">"value is longer than max_length"</span>, <span class="number">2</span>)
229 <span class="keyword">end</span>
230
231 <span class="keyword">local</span> exit_keys = {}
232 <span class="keyword">for</span> _, key <span class="keyword">in</span> <span class="global">ipairs</span>(opts.exit_keys <span class="keyword">or</span> {}) <span class="keyword">do</span>
233 exit_keys[key] = <span class="keyword">true</span>
234 <span class="keyword">end</span>
235 <span class="keyword">if</span> exit_keys[<span class="number">1</span>] == <span class="keyword">nil</span> <span class="keyword">then</span>
236 <span class="comment">-- nothing provided, default to Enter-key
237</span> exit_keys[<span class="number">1</span>] = key_sequences.enter
238 <span class="keyword">end</span>
239
240 <span class="keyword">local</span> self = {
241 value = value, <span class="comment">-- the default value
242</span> max_length = len, <span class="comment">-- the maximum length of the input
243</span> prompt = prompt, <span class="comment">-- the prompt to display
244</span> position = pos, <span class="comment">-- the current position in the input
245</span> drawn_before = <span class="keyword">false</span>, <span class="comment">-- if the prompt has been drawn
246</span> exit_keys = exit_keys, <span class="comment">-- the keys that will cause the readline to exit
247</span> }
248
249 <span class="global">setmetatable</span>(self, readline)
250 <span class="keyword">return</span> self
251<span class="keyword">end</span>
252
253
254
255<span class="comment">-- draw the prompt and the input value, and position the cursor.
256</span><span class="keyword">local</span> <span class="keyword">function</span> <span class="function-name">draw</span>(self, redraw)
257 <span class="keyword">if</span> redraw <span class="keyword">or</span> <span class="keyword">not</span> self.drawn_before <span class="keyword">then</span>
258 <span class="comment">-- we are at start of prompt
259</span> self.drawn_before = <span class="keyword">true</span>
260 <span class="keyword">else</span>
261 <span class="comment">-- we are at current cursor position, move to start of prompt
262</span> <span class="global">io</span>.<span class="function-name">write</span>(<span class="function-name">cursor_move_horiz</span>(-(#self.prompt + self.position)))
263 <span class="keyword">end</span>
264 <span class="comment">-- write prompt &amp; value
265</span> <span class="global">io</span>.<span class="function-name">write</span>(<span class="global">tostring</span>(self.prompt) .. <span class="global">tostring</span>(self.value))
266 <span class="comment">-- clear remainder of input size
267</span> <span class="global">io</span>.<span class="function-name">write</span>(<span class="global">string</span>.<span class="function-name">rep</span>(<span class="string">" "</span>, self.max_length - self.value.chars))
268 <span class="global">io</span>.<span class="function-name">write</span>(<span class="function-name">cursor_move_horiz</span>(-(self.max_length - self.value.chars)))
269 <span class="comment">-- move to cursor position
270</span> <span class="global">io</span>.<span class="function-name">write</span>(<span class="function-name">cursor_move_horiz</span>(-(#self.value + <span class="number">1</span> - self.position)))
271 <span class="global">io</span>.<span class="function-name">flush</span>()
272<span class="keyword">end</span>
273
274
275<span class="keyword">local</span> handle_key <span class="keyword">do</span> <span class="comment">-- keyboard input handler
276</span>
277 <span class="keyword">local</span> key_handlers
278 key_handlers = {
279 left = <span class="keyword">function</span>(self)
280 <span class="keyword">if</span> self.position == <span class="number">1</span> <span class="keyword">then</span>
281 <span class="function-name">bell</span>()
282 <span class="keyword">return</span>
283 <span class="keyword">end</span>
284
285 <span class="keyword">local</span> new_pos = self.position - <span class="number">1</span>
286 <span class="keyword">while</span> self.value[new_pos] == <span class="string">""</span> <span class="keyword">do</span> <span class="comment">-- skip empty strings; double width chars
287</span> new_pos = new_pos - <span class="number">1</span>
288 <span class="keyword">end</span>
289
290 <span class="global">io</span>.<span class="function-name">write</span>(<span class="function-name">cursor_move_horiz</span>(-(self.position - new_pos)))
291 <span class="global">io</span>.<span class="function-name">flush</span>()
292 self.position = new_pos
293 <span class="keyword">end</span>,
294
295 right = <span class="keyword">function</span>(self)
296 <span class="keyword">if</span> self.position == #self.value + <span class="number">1</span> <span class="keyword">then</span>
297 <span class="function-name">bell</span>()
298 <span class="keyword">return</span>
299 <span class="keyword">end</span>
300
301 <span class="keyword">local</span> new_pos = self.position + <span class="number">1</span>
302 <span class="keyword">while</span> self.value[new_pos] == <span class="string">""</span> <span class="keyword">do</span> <span class="comment">-- skip empty strings; double width chars
303</span> new_pos = new_pos + <span class="number">1</span>
304 <span class="keyword">end</span>
305
306 <span class="global">io</span>.<span class="function-name">write</span>(<span class="function-name">cursor_move_horiz</span>(new_pos - self.position))
307 <span class="global">io</span>.<span class="function-name">flush</span>()
308 self.position = new_pos
309 <span class="keyword">end</span>,
310
311 backspace = <span class="keyword">function</span>(self)
312 <span class="keyword">if</span> self.position == <span class="number">1</span> <span class="keyword">then</span>
313 <span class="function-name">bell</span>()
314 <span class="keyword">return</span>
315 <span class="keyword">end</span>
316
317 <span class="keyword">while</span> self.value[self.position - <span class="number">1</span>] == <span class="string">""</span> <span class="keyword">do</span> <span class="comment">-- remove empty strings; double width chars
318</span> <span class="global">io</span>.<span class="function-name">write</span>(<span class="function-name">cursor_move_horiz</span>(-<span class="number">1</span>))
319 self.position = self.position - <span class="number">1</span>
320 <span class="global">table</span>.<span class="function-name">remove</span>(self.value, self.position)
321 <span class="keyword">end</span>
322 <span class="comment">-- remove char itself
323</span> <span class="global">io</span>.<span class="function-name">write</span>(<span class="function-name">cursor_move_horiz</span>(-<span class="number">1</span>))
324 self.position = self.position - <span class="number">1</span>
325 <span class="global">table</span>.<span class="function-name">remove</span>(self.value, self.position)
326 self.value.chars = self.value.chars - <span class="number">1</span>
327 <span class="function-name">draw</span>(self)
328 <span class="keyword">end</span>,
329
330 home = <span class="keyword">function</span>(self)
331 <span class="keyword">local</span> new_pos = <span class="number">1</span>
332 <span class="global">io</span>.<span class="function-name">write</span>(<span class="function-name">cursor_move_horiz</span>(new_pos - self.position))
333 self.position = new_pos
334 <span class="keyword">end</span>,
335
336 [<span class="string">"end"</span>] = <span class="keyword">function</span>(self)
337 <span class="keyword">local</span> new_pos = #self.value + <span class="number">1</span>
338 <span class="global">io</span>.<span class="function-name">write</span>(<span class="function-name">cursor_move_horiz</span>(new_pos - self.position))
339 self.position = new_pos
340 <span class="keyword">end</span>,
341
342 delete = <span class="keyword">function</span>(self)
343 <span class="keyword">if</span> self.position &gt; #self.value <span class="keyword">then</span>
344 <span class="function-name">bell</span>()
345 <span class="keyword">return</span>
346 <span class="keyword">end</span>
347
348 key_handlers.<span class="function-name">right</span>(self)
349 key_handlers.<span class="function-name">backspace</span>(self)
350 <span class="keyword">end</span>,
351 }
352
353
354 <span class="comment">-- handles a single input key/ansi-sequence.
355</span> <span class="comment">-- @tparam string key the key or ansi-sequence (from <a href="../modules/system.html#readansi">system.readansi</a>)
356</span> <span class="comment">-- @tparam string keytype the type of the key, either "char" or "ansi" (from <a href="../modules/system.html#readansi">system.readansi</a>)
357</span> <span class="comment">-- @treturn string status the status of the key handling, either "ok", "exit_key" or an error message
358</span> <span class="keyword">function</span> <span class="function-name">handle_key</span>(self, key, keytype)
359 <span class="keyword">if</span> self.exit_keys[key] <span class="keyword">then</span>
360 <span class="comment">-- registered exit key
361</span> <span class="keyword">return</span> <span class="string">"exit_key"</span>
362 <span class="keyword">end</span>
363
364 <span class="keyword">local</span> handler = key_handlers[key_names[key] <span class="keyword">or</span> <span class="keyword">true</span> ]
365 <span class="keyword">if</span> handler <span class="keyword">then</span>
366 <span class="function-name">handler</span>(self)
367 <span class="keyword">return</span> <span class="string">"ok"</span>
368 <span class="keyword">end</span>
369
370 <span class="keyword">if</span> keytype == <span class="string">"ansi"</span> <span class="keyword">then</span>
371 <span class="comment">-- we got an ansi sequence, but dunno how to handle it, ignore
372</span> <span class="comment">-- print("unhandled ansi: ", key:sub(2,-1), string.byte(key, 1, -1))
373</span> <span class="function-name">bell</span>()
374 <span class="keyword">return</span> <span class="string">"ok"</span>
375 <span class="keyword">end</span>
376
377 <span class="comment">-- just a single key
378</span> <span class="keyword">if</span> key &lt; <span class="string">" "</span> <span class="keyword">then</span>
379 <span class="comment">-- control character
380</span> <span class="function-name">bell</span>()
381 <span class="keyword">return</span> <span class="string">"ok"</span>
382 <span class="keyword">end</span>
383
384 <span class="keyword">if</span> self.value.chars &gt;= self.max_length <span class="keyword">then</span>
385 <span class="function-name">bell</span>()
386 <span class="keyword">return</span> <span class="string">"ok"</span>
387 <span class="keyword">end</span>
388
389 <span class="comment">-- insert the key into the value
390</span> <span class="keyword">if</span> sys.<span class="function-name">utf8cwidth</span>(key) == <span class="number">2</span> <span class="keyword">then</span>
391 <span class="comment">-- double width character, insert empty string after it
392</span> <span class="global">table</span>.<span class="function-name">insert</span>(self.value, self.position, <span class="string">""</span>)
393 <span class="global">table</span>.<span class="function-name">insert</span>(self.value, self.position, key)
394 self.position = self.position + <span class="number">2</span>
395 <span class="global">io</span>.<span class="function-name">write</span>(<span class="function-name">cursor_move_horiz</span>(<span class="number">2</span>))
396 <span class="keyword">else</span>
397 <span class="global">table</span>.<span class="function-name">insert</span>(self.value, self.position, key)
398 self.position = self.position + <span class="number">1</span>
399 <span class="global">io</span>.<span class="function-name">write</span>(<span class="function-name">cursor_move_horiz</span>(<span class="number">1</span>))
400 <span class="keyword">end</span>
401 self.value.chars = self.value.chars + <span class="number">1</span>
402 <span class="function-name">draw</span>(self)
403 <span class="keyword">return</span> <span class="string">"ok"</span>
404 <span class="keyword">end</span>
405<span class="keyword">end</span>
406
407
408
409<span class="comment">--- Get_size returns the maximum size of the input box (prompt + input).
410</span><span class="comment">-- The size is in rows and columns. Columns is determined by
411</span><span class="comment">-- the prompt and the <code>max_length * 2</code> (characters can be double-width).
412</span><span class="comment">-- @treturn number the number of rows (always 1)
413</span><span class="comment">-- @treturn number the number of columns
414</span><span class="keyword">function</span> readline:<span class="function-name">get_size</span>()
415 <span class="keyword">return</span> <span class="number">1</span>, #self.prompt + self.max_length * <span class="number">2</span>
416<span class="keyword">end</span>
417
418
419
420<span class="comment">--- Get coordinates of the cursor in the input box (prompt + input).
421</span><span class="comment">-- The coordinates are 1-based. They are returned as row and column, within the
422</span><span class="comment">-- size as reported by <code>get_size</code>.
423</span><span class="comment">-- @treturn number the row of the cursor (always 1)
424</span><span class="comment">-- @treturn number the column of the cursor
425</span><span class="keyword">function</span> readline:<span class="function-name">get_cursor</span>()
426 <span class="keyword">return</span> <span class="number">1</span>, #self.prompt + self.position
427<span class="keyword">end</span>
428
429
430
431<span class="comment">--- Set the coordinates of the cursor in the input box (prompt + input).
432</span><span class="comment">-- The coordinates are 1-based. They are expected to be within the
433</span><span class="comment">-- size as reported by <code>get_size</code>, and beyond the prompt.
434</span><span class="comment">-- If the position is invalid, it will be corrected.
435</span><span class="comment">-- Use the results to check if the position was adjusted.
436</span><span class="comment">-- @tparam number row the row of the cursor (always 1)
437</span><span class="comment">-- @tparam number col the column of the cursor
438</span><span class="comment">-- @return results of get_cursor
439</span><span class="keyword">function</span> readline:<span class="function-name">set_cursor</span>(row, col)
440 <span class="keyword">local</span> l_prompt = #self.prompt
441 <span class="keyword">local</span> l_value = #self.value
442
443 <span class="keyword">if</span> col &lt; l_prompt + <span class="number">1</span> <span class="keyword">then</span>
444 col = l_prompt + <span class="number">1</span>
445 <span class="keyword">elseif</span> col &gt; l_prompt + l_value + <span class="number">1</span> <span class="keyword">then</span>
446 col = l_prompt + l_value + <span class="number">1</span>
447 <span class="keyword">end</span>
448
449 <span class="keyword">while</span> self.value[col - l_prompt] == <span class="string">""</span> <span class="keyword">do</span>
450 col = col - <span class="number">1</span> <span class="comment">-- on an empty string, so move back to start of double-width char
451</span> <span class="keyword">end</span>
452
453 <span class="keyword">local</span> new_pos = col - l_prompt
454
455 <span class="function-name">cursor_move_horiz</span>(self.position - new_pos)
456 <span class="global">io</span>.<span class="function-name">flush</span>()
457
458 self.position = new_pos
459 <span class="keyword">return</span> self:<span class="function-name">get_cursor</span>()
460<span class="keyword">end</span>
461
462
463
464<span class="comment">--- Read a line of input from the user.
465</span><span class="comment">-- It will first print the <code>prompt</code> and then wait for input. Ensure the cursor
466</span><span class="comment">-- is at the correct position before calling this function. This function will
467</span><span class="comment">-- do all cursor movements in a relative way.
468</span><span class="comment">-- Can be called again after an exit-key or timeout has occurred. Just make sure
469</span><span class="comment">-- the cursor is at the same position where is was when it returned the last time.
470</span><span class="comment">-- Alternatively the cursor can be set to the position of the prompt (the position
471</span><span class="comment">-- the cursor was in before the first call), and the parameter <code>redraw</code> can be set
472</span><span class="comment">-- to <code>true</code>.
473</span><span class="comment">-- @tparam[opt=math.huge] number timeout the maximum time to wait for input in seconds
474</span><span class="comment">-- @tparam[opt=false] boolean redraw if <code>true</code> the prompt will be redrawn (cursor must be at prompt position!)
475</span><span class="comment">-- @treturn[1] string the input string as entered the user
476</span><span class="comment">-- @treturn[1] string the exit-key used to exit the readline (see <code>new</code>)
477</span><span class="comment">-- @treturn[2] nil when input is incomplete
478</span><span class="comment">-- @treturn[2] string error message, the reason why the input is incomplete, <code>&quot;timeout&quot;</code>, or an error reading a key
479</span><span class="keyword">function</span> readline:<span class="function-name">__call</span>(timeout, redraw)
480 <span class="function-name">draw</span>(self, redraw)
481 timeout = timeout <span class="keyword">or</span> <span class="global">math</span>.huge
482 <span class="keyword">local</span> timeout_end = sys.<span class="function-name">gettime</span>() + timeout
483
484 <span class="keyword">while</span> <span class="keyword">true</span> <span class="keyword">do</span>
485 <span class="keyword">local</span> key, keytype = sys.<span class="function-name">readansi</span>(timeout_end - sys.<span class="function-name">gettime</span>())
486 <span class="keyword">if</span> <span class="keyword">not</span> key <span class="keyword">then</span>
487 <span class="comment">-- error or timeout
488</span> <span class="keyword">return</span> <span class="keyword">nil</span>, keytype
489 <span class="keyword">end</span>
490
491 <span class="keyword">local</span> status = <span class="function-name">handle_key</span>(self, key, keytype)
492 <span class="keyword">if</span> status == <span class="string">"exit_key"</span> <span class="keyword">then</span>
493 <span class="keyword">return</span> <span class="global">tostring</span>(self.value), key
494
495 <span class="keyword">elseif</span> status ~= <span class="string">"ok"</span> <span class="keyword">then</span>
496 <span class="global">error</span>(<span class="string">"unknown status received: "</span> .. <span class="global">tostring</span>(status))
497 <span class="keyword">end</span>
498 <span class="keyword">end</span>
499<span class="keyword">end</span>
500
501
502
503<span class="comment">-- return readline -- normally we'd return here, but for the example we continue
504</span>
505
506
507
508<span class="keyword">local</span> backup = sys.<span class="function-name">termbackup</span>()
509
510<span class="comment">-- setup Windows console to handle ANSI processing
511</span>sys.<span class="function-name">setconsoleflags</span>(<span class="global">io</span>.stdout, sys.<span class="function-name">getconsoleflags</span>(<span class="global">io</span>.stdout) + sys.COF_VIRTUAL_TERMINAL_PROCESSING)
512sys.<span class="function-name">setconsoleflags</span>(<span class="global">io</span>.stdin, sys.<span class="function-name">getconsoleflags</span>(<span class="global">io</span>.stdin) + sys.CIF_VIRTUAL_TERMINAL_INPUT)
513<span class="comment">-- set output to UTF-8
514</span>sys.<span class="function-name">setconsoleoutputcp</span>(sys.CODEPAGE_UTF8)
515
516<span class="comment">-- setup Posix terminal to disable canonical mode and echo
517</span>sys.<span class="function-name">tcsetattr</span>(<span class="global">io</span>.stdin, sys.TCSANOW, {
518 lflag = sys.<span class="function-name">tcgetattr</span>(<span class="global">io</span>.stdin).lflag - sys.L_ICANON - sys.L_ECHO,
519})
520<span class="comment">-- setup stdin to non-blocking mode
521</span>sys.<span class="function-name">setnonblock</span>(<span class="global">io</span>.stdin, <span class="keyword">true</span>)
522
523
524<span class="keyword">local</span> rl = readline.<span class="function-name">new</span>{
525 prompt = <span class="string">"Enter something: "</span>,
526 max_length = <span class="number">60</span>,
527 value = <span class="string">"Hello, 你-好 World 🚀!"</span>,
528 <span class="comment">-- position = 2,
529</span> exit_keys = {key_sequences.enter, <span class="string">"\27"</span>, <span class="string">"\t"</span>, <span class="string">"\27[Z"</span>}, <span class="comment">-- enter, escape, tab, shift-tab
530</span>}
531
532
533<span class="keyword">local</span> result, key = <span class="function-name">rl</span>()
534<span class="global">print</span>(<span class="string">""</span>) <span class="comment">-- newline after input, to move cursor down from the input line
535</span><span class="global">print</span>(<span class="string">"Result (string): '"</span> .. result .. <span class="string">"'"</span>)
536<span class="global">print</span>(<span class="string">"Result (bytes):"</span>, result:<span class="function-name">byte</span>(<span class="number">1</span>,-<span class="number">1</span>))
537<span class="global">print</span>(<span class="string">"Exit-Key (bytes):"</span>, key:<span class="function-name">byte</span>(<span class="number">1</span>,-<span class="number">1</span>))
538
539
540<span class="comment">-- Clean up afterwards
541</span>sys.<span class="function-name">termrestore</span>(backup)</pre>
542
543
544</div> <!-- id="content" -->
545</div> <!-- id="main" -->
546<div id="about">
547<i>generated by <a href="http://github.com/lunarmodules/LDoc">LDoc 1.5.0</a></i>
548<i style="float:right;">Last updated 2024-06-20 23:11:37 </i>
549</div> <!-- id="about" -->
550</div> <!-- id="container" -->
551</body>
552</html>
diff --git a/docs/examples/spinner.lua.html b/docs/examples/spinner.lua.html
new file mode 100644
index 0000000..181cbe5
--- /dev/null
+++ b/docs/examples/spinner.lua.html
@@ -0,0 +1,144 @@
1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3<html>
4<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
5<head>
6 <title>Lua-System docs</title>
7 <link rel="stylesheet" href="../ldoc.css" type="text/css" />
8</head>
9<body>
10
11<div id="container">
12
13<div id="product">
14 <div id="product_logo"></div>
15 <div id="product_name"><big><b></b></big></div>
16 <div id="product_description"></div>
17</div> <!-- id="product" -->
18
19
20<div id="main">
21
22
23<!-- Menu -->
24
25<div id="navigation">
26<br/>
27<h1>Lua-System</h1>
28
29
30<ul>
31 <li><a href="../index.html">Index</a></li>
32</ul>
33
34
35
36<h2>Examples</h2>
37<ul class="nowrap">
38 <li><a href="../examples/compat.lua.html">compat.lua</a></li>
39 <li><a href="../examples/flag_debugging.lua.html">flag_debugging.lua</a></li>
40 <li><a href="../examples/password_input.lua.html">password_input.lua</a></li>
41 <li><a href="../examples/read.lua.html">read.lua</a></li>
42 <li><a href="../examples/readline.lua.html">readline.lua</a></li>
43 <li><strong>spinner.lua</strong></li>
44 <li><a href="../examples/spiral_snake.lua.html">spiral_snake.lua</a></li>
45 <li><a href="../examples/terminalsize.lua.html">terminalsize.lua</a></li>
46</ul>
47<h2>Modules</h2>
48<ul class="nowrap">
49 <li><a href="../modules/system.html">system</a></li>
50</ul>
51<h2>Classes</h2>
52<ul class="nowrap">
53 <li><a href="../classes/bitflags.html">bitflags</a></li>
54</ul>
55<h2>Topics</h2>
56<ul class="">
57 <li><a href="../topics/01-introduction.md.html">1. Introduction</a></li>
58 <li><a href="../topics/02-development.md.html">2. Development</a></li>
59 <li><a href="../topics/03-terminal.md.html">3. Terminal functionality</a></li>
60 <li><a href="../topics/CHANGELOG.md.html">CHANGELOG</a></li>
61 <li><a href="../topics/LICENSE.md.html">MIT License</a></li>
62</ul>
63
64</div>
65
66<div id="content">
67
68 <h2>spinner.lua</h2>
69<pre>
70<span class="keyword">local</span> sys = <span class="global">require</span>(<span class="string">"system"</span>)
71
72<span class="global">print</span> <span class="string">[[
73
74An example to display a spinner, whilst a long running task executes.
75
76]]</span>
77
78
79<span class="comment">-- start make backup, to auto-restore on exit
80</span>sys.<span class="function-name">autotermrestore</span>()
81<span class="comment">-- configure console
82</span>sys.<span class="function-name">setconsoleflags</span>(<span class="global">io</span>.stdin, sys.<span class="function-name">getconsoleflags</span>(<span class="global">io</span>.stdin) - sys.CIF_ECHO_INPUT - sys.CIF_LINE_INPUT)
83<span class="keyword">local</span> of = sys.<span class="function-name">tcgetattr</span>(<span class="global">io</span>.stdin)
84sys.<span class="function-name">tcsetattr</span>(<span class="global">io</span>.stdin, sys.TCSANOW, { lflag = of.lflag - sys.L_ICANON - sys.L_ECHO })
85sys.<span class="function-name">setnonblock</span>(<span class="global">io</span>.stdin, <span class="keyword">true</span>)
86
87
88
89<span class="keyword">local</span> <span class="keyword">function</span> <span class="function-name">hideCursor</span>()
90 <span class="global">io</span>.<span class="function-name">write</span>(<span class="string">"\27[?25l"</span>)
91 <span class="global">io</span>.<span class="function-name">flush</span>()
92<span class="keyword">end</span>
93
94<span class="keyword">local</span> <span class="keyword">function</span> <span class="function-name">showCursor</span>()
95 <span class="global">io</span>.<span class="function-name">write</span>(<span class="string">"\27[?25h"</span>)
96 <span class="global">io</span>.<span class="function-name">flush</span>()
97<span class="keyword">end</span>
98
99<span class="keyword">local</span> <span class="keyword">function</span> <span class="function-name">left</span>(n)
100 <span class="global">io</span>.<span class="function-name">write</span>(<span class="string">"\27["</span>,n <span class="keyword">or</span> <span class="number">1</span>,<span class="string">"D"</span>)
101 <span class="global">io</span>.<span class="function-name">flush</span>()
102<span class="keyword">end</span>
103
104
105
106<span class="keyword">local</span> spinner <span class="keyword">do</span>
107 <span class="keyword">local</span> spin = <span class="string">[[|/-\]]</span>
108 <span class="keyword">local</span> i = <span class="number">1</span>
109 spinner = <span class="keyword">function</span>()
110 <span class="function-name">hideCursor</span>()
111 <span class="global">io</span>.<span class="function-name">write</span>(spin:<span class="function-name">sub</span>(i, i))
112 <span class="function-name">left</span>()
113 i = i + <span class="number">1</span>
114 <span class="keyword">if</span> i &gt; #spin <span class="keyword">then</span> i = <span class="number">1</span> <span class="keyword">end</span>
115
116 <span class="keyword">if</span> sys.<span class="function-name">readkey</span>(<span class="number">0</span>) ~= <span class="keyword">nil</span> <span class="keyword">then</span>
117 <span class="keyword">while</span> sys.<span class="function-name">readkey</span>(<span class="number">0</span>) ~= <span class="keyword">nil</span> <span class="keyword">do</span> <span class="keyword">end</span> <span class="comment">-- consume keys pressed
118</span> <span class="global">io</span>.<span class="function-name">write</span>(<span class="string">" "</span>);
119 <span class="function-name">left</span>()
120 <span class="function-name">showCursor</span>()
121 <span class="keyword">return</span> <span class="keyword">true</span>
122 <span class="keyword">else</span>
123 <span class="keyword">return</span> <span class="keyword">false</span>
124 <span class="keyword">end</span>
125 <span class="keyword">end</span>
126<span class="keyword">end</span>
127
128<span class="global">io</span>.stdout:<span class="function-name">write</span>(<span class="string">"press any key to stop the spinner... "</span>)
129<span class="keyword">while</span> <span class="keyword">not</span> <span class="function-name">spinner</span>() <span class="keyword">do</span>
130 sys.<span class="function-name">sleep</span>(<span class="number">0.1</span>)
131<span class="keyword">end</span>
132
133<span class="global">print</span>(<span class="string">"Done!"</span>)</pre>
134
135
136</div> <!-- id="content" -->
137</div> <!-- id="main" -->
138<div id="about">
139<i>generated by <a href="http://github.com/lunarmodules/LDoc">LDoc 1.5.0</a></i>
140<i style="float:right;">Last updated 2024-06-20 23:11:37 </i>
141</div> <!-- id="about" -->
142</div> <!-- id="container" -->
143</body>
144</html>
diff --git a/docs/examples/spiral_snake.lua.html b/docs/examples/spiral_snake.lua.html
new file mode 100644
index 0000000..7ebb838
--- /dev/null
+++ b/docs/examples/spiral_snake.lua.html
@@ -0,0 +1,152 @@
1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3<html>
4<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
5<head>
6 <title>Lua-System docs</title>
7 <link rel="stylesheet" href="../ldoc.css" type="text/css" />
8</head>
9<body>
10
11<div id="container">
12
13<div id="product">
14 <div id="product_logo"></div>
15 <div id="product_name"><big><b></b></big></div>
16 <div id="product_description"></div>
17</div> <!-- id="product" -->
18
19
20<div id="main">
21
22
23<!-- Menu -->
24
25<div id="navigation">
26<br/>
27<h1>Lua-System</h1>
28
29
30<ul>
31 <li><a href="../index.html">Index</a></li>
32</ul>
33
34
35
36<h2>Examples</h2>
37<ul class="nowrap">
38 <li><a href="../examples/compat.lua.html">compat.lua</a></li>
39 <li><a href="../examples/flag_debugging.lua.html">flag_debugging.lua</a></li>
40 <li><a href="../examples/password_input.lua.html">password_input.lua</a></li>
41 <li><a href="../examples/read.lua.html">read.lua</a></li>
42 <li><a href="../examples/readline.lua.html">readline.lua</a></li>
43 <li><a href="../examples/spinner.lua.html">spinner.lua</a></li>
44 <li><strong>spiral_snake.lua</strong></li>
45 <li><a href="../examples/terminalsize.lua.html">terminalsize.lua</a></li>
46</ul>
47<h2>Modules</h2>
48<ul class="nowrap">
49 <li><a href="../modules/system.html">system</a></li>
50</ul>
51<h2>Classes</h2>
52<ul class="nowrap">
53 <li><a href="../classes/bitflags.html">bitflags</a></li>
54</ul>
55<h2>Topics</h2>
56<ul class="">
57 <li><a href="../topics/01-introduction.md.html">1. Introduction</a></li>
58 <li><a href="../topics/02-development.md.html">2. Development</a></li>
59 <li><a href="../topics/03-terminal.md.html">3. Terminal functionality</a></li>
60 <li><a href="../topics/CHANGELOG.md.html">CHANGELOG</a></li>
61 <li><a href="../topics/LICENSE.md.html">MIT License</a></li>
62</ul>
63
64</div>
65
66<div id="content">
67
68 <h2>spiral_snake.lua</h2>
69<pre>
70<span class="keyword">local</span> sys = <span class="global">require</span> <span class="string">"system"</span>
71
72<span class="global">print</span> <span class="string">[[
73
74This example will draw a snake like spiral on the screen. Showing ANSI escape
75codes for moving the cursor around.
76
77]]</span>
78
79<span class="comment">-- backup term settings with auto-restore on exit
80</span>sys.<span class="function-name">autotermrestore</span>()
81
82<span class="comment">-- setup Windows console to handle ANSI processing
83</span>sys.<span class="function-name">setconsoleflags</span>(<span class="global">io</span>.stdout, sys.<span class="function-name">getconsoleflags</span>(<span class="global">io</span>.stdout) + sys.COF_VIRTUAL_TERMINAL_PROCESSING)
84
85<span class="comment">-- start drawing the spiral.
86</span><span class="comment">-- start from current pos, then right, then up, then left, then down, and again.
87</span><span class="keyword">local</span> x, y = <span class="number">1</span>, <span class="number">1</span> <span class="comment">-- current position
88</span><span class="keyword">local</span> dx, dy = <span class="number">1</span>, <span class="number">0</span> <span class="comment">-- direction after each step
89</span><span class="keyword">local</span> wx, wy = <span class="number">30</span>, <span class="number">30</span> <span class="comment">-- width and height of the room
90</span><span class="keyword">local</span> mx, my = <span class="number">1</span>, <span class="number">1</span> <span class="comment">-- margin
91</span>
92<span class="comment">-- commands to move the cursor
93</span><span class="keyword">local</span> move_left = <span class="string">"\27[1D"</span>
94<span class="keyword">local</span> move_right = <span class="string">"\27[1C"</span>
95<span class="keyword">local</span> move_up = <span class="string">"\27[1A"</span>
96<span class="keyword">local</span> move_down = <span class="string">"\27[1B"</span>
97
98<span class="comment">-- create room: 30 empty lines
99</span><span class="global">print</span>((<span class="string">"\n"</span>):<span class="function-name">rep</span>(wy))
100<span class="keyword">local</span> move = move_right
101
102<span class="keyword">while</span> wx &gt; <span class="number">0</span> <span class="keyword">and</span> wy &gt; <span class="number">0</span> <span class="keyword">do</span>
103 sys.<span class="function-name">sleep</span>(<span class="number">0.01</span>) <span class="comment">-- slow down the drawing a little
104</span> <span class="global">io</span>.<span class="function-name">write</span>(<span class="string">"*"</span> .. move_left .. move )
105 <span class="global">io</span>.<span class="function-name">flush</span>()
106 x = x + dx
107 y = y + dy
108
109 <span class="keyword">if</span> x &gt; wx <span class="keyword">and</span> move == move_right <span class="keyword">then</span>
110 <span class="comment">-- end of move right
111</span> dx = <span class="number">0</span>
112 dy = <span class="number">1</span>
113 move = move_up
114 wy = wy - <span class="number">1</span>
115 my = my + <span class="number">1</span>
116 <span class="keyword">elseif</span> y &gt; wy <span class="keyword">and</span> move == move_up <span class="keyword">then</span>
117 <span class="comment">-- end of move up
118</span> dx = -<span class="number">1</span>
119 dy = <span class="number">0</span>
120 move = move_left
121 wx = wx - <span class="number">1</span>
122 mx = mx + <span class="number">1</span>
123 <span class="keyword">elseif</span> x &lt; mx <span class="keyword">and</span> move == move_left <span class="keyword">then</span>
124 <span class="comment">-- end of move left
125</span> dx = <span class="number">0</span>
126 dy = -<span class="number">1</span>
127 move = move_down
128 wy = wy - <span class="number">1</span>
129 my = my + <span class="number">1</span>
130 <span class="keyword">elseif</span> y &lt; my <span class="keyword">and</span> move == move_down <span class="keyword">then</span>
131 <span class="comment">-- end of move down
132</span> dx = <span class="number">1</span>
133 dy = <span class="number">0</span>
134 move = move_right
135 wx = wx - <span class="number">1</span>
136 mx = mx + <span class="number">1</span>
137 <span class="keyword">end</span>
138<span class="keyword">end</span>
139
140<span class="global">io</span>.<span class="function-name">write</span>(move_down:<span class="function-name">rep</span>(<span class="number">15</span>))
141<span class="global">print</span>(<span class="string">"\nDone!"</span>)</pre>
142
143
144</div> <!-- id="content" -->
145</div> <!-- id="main" -->
146<div id="about">
147<i>generated by <a href="http://github.com/lunarmodules/LDoc">LDoc 1.5.0</a></i>
148<i style="float:right;">Last updated 2024-06-20 23:11:37 </i>
149</div> <!-- id="about" -->
150</div> <!-- id="container" -->
151</body>
152</html>
diff --git a/docs/examples/terminalsize.lua.html b/docs/examples/terminalsize.lua.html
new file mode 100644
index 0000000..d7f902d
--- /dev/null
+++ b/docs/examples/terminalsize.lua.html
@@ -0,0 +1,117 @@
1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3<html>
4<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
5<head>
6 <title>Lua-System docs</title>
7 <link rel="stylesheet" href="../ldoc.css" type="text/css" />
8</head>
9<body>
10
11<div id="container">
12
13<div id="product">
14 <div id="product_logo"></div>
15 <div id="product_name"><big><b></b></big></div>
16 <div id="product_description"></div>
17</div> <!-- id="product" -->
18
19
20<div id="main">
21
22
23<!-- Menu -->
24
25<div id="navigation">
26<br/>
27<h1>Lua-System</h1>
28
29
30<ul>
31 <li><a href="../index.html">Index</a></li>
32</ul>
33
34
35
36<h2>Examples</h2>
37<ul class="nowrap">
38 <li><a href="../examples/compat.lua.html">compat.lua</a></li>
39 <li><a href="../examples/flag_debugging.lua.html">flag_debugging.lua</a></li>
40 <li><a href="../examples/password_input.lua.html">password_input.lua</a></li>
41 <li><a href="../examples/read.lua.html">read.lua</a></li>
42 <li><a href="../examples/readline.lua.html">readline.lua</a></li>
43 <li><a href="../examples/spinner.lua.html">spinner.lua</a></li>
44 <li><a href="../examples/spiral_snake.lua.html">spiral_snake.lua</a></li>
45 <li><strong>terminalsize.lua</strong></li>
46</ul>
47<h2>Modules</h2>
48<ul class="nowrap">
49 <li><a href="../modules/system.html">system</a></li>
50</ul>
51<h2>Classes</h2>
52<ul class="nowrap">
53 <li><a href="../classes/bitflags.html">bitflags</a></li>
54</ul>
55<h2>Topics</h2>
56<ul class="">
57 <li><a href="../topics/01-introduction.md.html">1. Introduction</a></li>
58 <li><a href="../topics/02-development.md.html">2. Development</a></li>
59 <li><a href="../topics/03-terminal.md.html">3. Terminal functionality</a></li>
60 <li><a href="../topics/CHANGELOG.md.html">CHANGELOG</a></li>
61 <li><a href="../topics/LICENSE.md.html">MIT License</a></li>
62</ul>
63
64</div>
65
66<div id="content">
67
68 <h2>terminalsize.lua</h2>
69<pre>
70<span class="keyword">local</span> sys = <span class="global">require</span>(<span class="string">"system"</span>)
71
72sys.<span class="function-name">autotermrestore</span>() <span class="comment">-- set up auto restore of terminal settings on exit
73</span>
74<span class="comment">-- setup Windows console to handle ANSI processing
75</span>sys.<span class="function-name">setconsoleflags</span>(<span class="global">io</span>.stdout, sys.<span class="function-name">getconsoleflags</span>(<span class="global">io</span>.stdout) + sys.COF_VIRTUAL_TERMINAL_PROCESSING)
76sys.<span class="function-name">setconsoleflags</span>(<span class="global">io</span>.stdin, sys.<span class="function-name">getconsoleflags</span>(<span class="global">io</span>.stdin) + sys.CIF_VIRTUAL_TERMINAL_INPUT)
77
78<span class="comment">-- setup Posix to disable canonical mode and echo
79</span><span class="keyword">local</span> of_attr = sys.<span class="function-name">tcgetattr</span>(<span class="global">io</span>.stdin)
80sys.<span class="function-name">setnonblock</span>(<span class="global">io</span>.stdin, <span class="keyword">true</span>)
81sys.<span class="function-name">tcsetattr</span>(<span class="global">io</span>.stdin, sys.TCSANOW, {
82 lflag = of_attr.lflag - sys.L_ICANON - sys.L_ECHO, <span class="comment">-- disable canonical mode and echo
83</span>})
84
85
86<span class="comment">-- generate string to move cursor horizontally
87</span><span class="comment">-- positive goes right, negative goes left
88</span><span class="keyword">local</span> <span class="keyword">function</span> <span class="function-name">cursor_move_horiz</span>(n)
89 <span class="keyword">if</span> n == <span class="number">0</span> <span class="keyword">then</span>
90 <span class="keyword">return</span> <span class="string">""</span>
91 <span class="keyword">end</span>
92 <span class="keyword">return</span> <span class="string">"\27["</span> .. (n &gt; <span class="number">0</span> <span class="keyword">and</span> n <span class="keyword">or</span> -n) .. (n &gt; <span class="number">0</span> <span class="keyword">and</span> <span class="string">"C"</span> <span class="keyword">or</span> <span class="string">"D"</span>)
93<span class="keyword">end</span>
94
95
96<span class="keyword">local</span> rows, cols
97<span class="global">print</span>(<span class="string">"Change the terminal window size, press any key to exit"</span>)
98<span class="keyword">while</span> <span class="keyword">not</span> sys.<span class="function-name">readansi</span>(<span class="number">0.2</span>) <span class="keyword">do</span> <span class="comment">-- use readansi to not leave stray bytes in the input buffer
99</span> <span class="keyword">local</span> nrows, ncols = sys.<span class="function-name">termsize</span>()
100 <span class="keyword">if</span> rows ~= nrows <span class="keyword">or</span> cols ~= ncols <span class="keyword">then</span>
101 rows, cols = nrows, ncols
102 <span class="keyword">local</span> text = <span class="string">"Terminal size: "</span> .. rows .. <span class="string">"x"</span> .. cols .. <span class="string">" "</span>
103 <span class="global">io</span>.<span class="function-name">write</span>(text .. <span class="function-name">cursor_move_horiz</span>(-#text))
104 <span class="global">io</span>.<span class="function-name">flush</span>()
105 <span class="keyword">end</span>
106<span class="keyword">end</span></pre>
107
108
109</div> <!-- id="content" -->
110</div> <!-- id="main" -->
111<div id="about">
112<i>generated by <a href="http://github.com/lunarmodules/LDoc">LDoc 1.5.0</a></i>
113<i style="float:right;">Last updated 2024-06-20 23:11:37 </i>
114</div> <!-- id="about" -->
115</div> <!-- id="container" -->
116</body>
117</html>