aboutsummaryrefslogtreecommitdiff
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
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
-rw-r--r--CHANGELOG.md14
-rw-r--r--LICENSE.md2
-rw-r--r--docs/classes/bitflags.html305
-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
-rw-r--r--docs/index.html369
-rw-r--r--docs/modules/system.html1418
-rw-r--r--docs/topics/01-introduction.md.html27
-rw-r--r--docs/topics/02-development.md.html91
-rw-r--r--docs/topics/03-terminal.md.html225
-rw-r--r--docs/topics/CHANGELOG.md.html55
-rw-r--r--docs/topics/LICENSE.md.html29
-rw-r--r--rockspecs/luasystem-0.4.0-1.rockspec85
-rw-r--r--src/core.c5
20 files changed, 3774 insertions, 311 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index eb85c94..a3544ea 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -28,6 +28,20 @@ The scope of what is covered by the version number excludes:
28 28
29## Version history 29## Version history
30 30
31### Version 0.4.0, released 20-Jun-2024
32
33- Feat: `getconsoleflags` and `setconsoleflags` for getting/setting the current console configuration flags on Windows
34- Feat: `getconsolecp` and `setconsolecp` for getting/setting the console codepage on Windows
35- Feat: `getconsoleoutputcp` and `setconsoleoutputcp` for getting/setting the console output codepage on Windows
36- Feat: `tcgetattr` and `tcsetattr` for getting/setting the current console configuration flags on Posix
37- Feat: `getnonblock` and `setnonblock` for getting/setting the non-blocking flag on Posix
38- Feat: `bitflags`: a support feature for the above flag type controls to facilitate bit manipulation without resorting to binary operations (to also support PuC Lua 5.1)
39- Feat: `readkey` reads a keyboard input from `stdin` in a non-blocking way (utf8, also on Windows)
40- Feat: `readansi` reads a keyboard input from `stdin` in a non-blocking way, parses ansi and utf8 sequences
41- Feat: `termsize` gets the current terminal size in rows and columns
42- Feat: `utf8cwidth` and `utf8swidth` for getting the display width (in columns) of respectively a single utf8 character, or a utf8 string
43- Feat: helpers; `termbackup`, `termrestore`, `autotermrestore`, and `termwrap` for managing the many terminal settings on all platforms.
44
31### Version 0.3.0, released 15-Dec-2023 45### Version 0.3.0, released 15-Dec-2023
32 46
33- Feat: on Windows `sleep` now has a precision parameter 47- Feat: on Windows `sleep` now has a precision parameter
diff --git a/LICENSE.md b/LICENSE.md
index df2befb..16c86d0 100644
--- a/LICENSE.md
+++ b/LICENSE.md
@@ -1,6 +1,6 @@
1# MIT License 1# MIT License
2 2
3### Copyright (c) 2016-2023 Oscar Lim 3### Copyright (c) 2016-2024 Oscar Lim
4 4
5Permission is hereby granted, free of charge, to any person obtaining a copy of 5Permission is hereby granted, free of charge, to any person obtaining a copy of
6this software and associated documentation files (the "Software"), to deal in 6this software and associated documentation files (the "Software"), to deal in
diff --git a/docs/classes/bitflags.html b/docs/classes/bitflags.html
new file mode 100644
index 0000000..f063149
--- /dev/null
+++ b/docs/classes/bitflags.html
@@ -0,0 +1,305 @@
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<h2>Contents</h2>
35<ul>
36<li><a href="#Bit_flags">Bit flags </a></li>
37</ul>
38
39
40<h2>Classes</h2>
41<ul class="nowrap">
42 <li><strong>bitflags</strong></li>
43</ul>
44<h2>Modules</h2>
45<ul class="nowrap">
46 <li><a href="../modules/system.html">system</a></li>
47</ul>
48<h2>Topics</h2>
49<ul class="">
50 <li><a href="../topics/01-introduction.md.html">1. Introduction</a></li>
51 <li><a href="../topics/02-development.md.html">2. Development</a></li>
52 <li><a href="../topics/03-terminal.md.html">3. Terminal functionality</a></li>
53 <li><a href="../topics/CHANGELOG.md.html">CHANGELOG</a></li>
54 <li><a href="../topics/LICENSE.md.html">MIT License</a></li>
55</ul>
56<h2>Examples</h2>
57<ul class="nowrap">
58 <li><a href="../examples/compat.lua.html">compat.lua</a></li>
59 <li><a href="../examples/flag_debugging.lua.html">flag_debugging.lua</a></li>
60 <li><a href="../examples/password_input.lua.html">password_input.lua</a></li>
61 <li><a href="../examples/read.lua.html">read.lua</a></li>
62 <li><a href="../examples/readline.lua.html">readline.lua</a></li>
63 <li><a href="../examples/spinner.lua.html">spinner.lua</a></li>
64 <li><a href="../examples/spiral_snake.lua.html">spiral_snake.lua</a></li>
65 <li><a href="../examples/terminalsize.lua.html">terminalsize.lua</a></li>
66</ul>
67
68</div>
69
70<div id="content">
71
72<h1>Class <code>bitflags</code></h1>
73<p>Bitflags module.</p>
74<p> The bitflag object makes it easy to manipulate flags in a bitmask.</p>
75
76<p> It has metamethods that do the hard work, adding flags sets them, substracting
77 unsets them. Comparing flags checks if all flags in the second set are also set
78 in the first set. The <code>has</code> method checks if all flags in the second set are
79 also set in the first set, but behaves slightly different.</p>
80
81<p> Indexing allows checking values or setting them by bit index (eg. 0-7 for flags
82 in the first byte).</p>
83
84<p> <em>NOTE</em>: unavailable flags (eg. Windows flags on a Posix system) should not be
85 omitted, but be assigned a value of 0. This is because the <code>has</code> method will
86 return <code>false</code> if the flags are checked and the value is 0.</p>
87
88<p> See <a href="../classes/bitflags.html#system.bitflag">system.bitflag</a> (the constructor) for extensive examples on usage.</p>
89
90
91<h2><a href="#Bit_flags">Bit flags </a></h2>
92<table class="function_list">
93 <tr>
94 <td class="name" nowrap><a href="#bitflag:has_all_of">bitflag:has_all_of (subset)</a></td>
95 <td class="summary">Checks if all the flags in the given subset are set.</td>
96 </tr>
97 <tr>
98 <td class="name" nowrap><a href="#bitflag:has_any_of">bitflag:has_any_of (subset)</a></td>
99 <td class="summary">Checks if any of the flags in the given subset are set.</td>
100 </tr>
101 <tr>
102 <td class="name" nowrap><a href="#bitflag:value">bitflag:value ()</a></td>
103 <td class="summary">Retrieves the numeric value of the bitflag object.</td>
104 </tr>
105 <tr>
106 <td class="name" nowrap><a href="#system.bitflag">system.bitflag ([value=0])</a></td>
107 <td class="summary">Creates a new bitflag object from the given value.</td>
108 </tr>
109</table>
110
111<br/>
112<br/>
113
114
115 <h2 class="section-header has-description"><a name="Bit_flags"></a>Bit flags </h2>
116
117 <div class="section-description">
118 Bitflag objects can be used to easily manipulate and compare bit flags.
119 These are primarily for use with the terminal functions, but can be used
120 in other places as well.
121 </div>
122 <dl class="function">
123 <dt>
124 <a name = "bitflag:has_all_of"></a>
125 <strong>bitflag:has_all_of (subset)</strong>
126 </dt>
127 <dd>
128 Checks if all the flags in the given subset are set.
129If the flags to check has a value <code>0</code>, it will always return <code>false</code>. So if there are flags that are
130unsupported on a platform, they can be set to 0 and the <a href="../classes/bitflags.html#bitflag:has_all_of">has_all_of</a> function will
131return <code>false</code> if the flags are checked.
132
133
134 <h3>Parameters:</h3>
135 <ul>
136 <li><span class="parameter">subset</span>
137 <span class="types"><a class="type" href="../classes/bitflags.html#system.bitflag">bitflag</a></span>
138 the flags to check for.
139 </li>
140 </ul>
141
142 <h3>Returns:</h3>
143 <ol>
144
145 <span class="types"><span class="type">boolean</span></span>
146 true if all the flags are set, false otherwise.
147 </ol>
148
149
150
151 <h3>Usage:</h3>
152 <ul>
153 <pre class="example"><span class="keyword">local</span> sys = <span class="global">require</span> <span class="string">'system'</span>
154<span class="keyword">local</span> flags = sys.<span class="function-name">bitflag</span>(<span class="number">12</span>) <span class="comment">-- b1100
155</span><span class="keyword">local</span> myflags = sys.<span class="function-name">bitflag</span>(<span class="number">15</span>) <span class="comment">-- b1111
156</span><span class="global">print</span>(flags:<span class="function-name">has_all_of</span>(myflags)) <span class="comment">-- false, not all bits in myflags are set in flags
157</span><span class="global">print</span>(myflags:<span class="function-name">has_all_of</span>(flags)) <span class="comment">-- true, all bits in flags are set in myflags</span></pre>
158 </ul>
159
160</dd>
161 <dt>
162 <a name = "bitflag:has_any_of"></a>
163 <strong>bitflag:has_any_of (subset)</strong>
164 </dt>
165 <dd>
166 Checks if any of the flags in the given subset are set.
167If the flags to check has a value <code>0</code>, it will always return <code>false</code>. So if there are flags that are
168unsupported on a platform, they can be set to 0 and the <a href="../classes/bitflags.html#bitflag:has_any_of">has_any_of</a> function will
169return <code>false</code> if the flags are checked.
170
171
172 <h3>Parameters:</h3>
173 <ul>
174 <li><span class="parameter">subset</span>
175 <span class="types"><a class="type" href="../classes/bitflags.html#system.bitflag">bitflag</a></span>
176 the flags to check for.
177 </li>
178 </ul>
179
180 <h3>Returns:</h3>
181 <ol>
182
183 <span class="types"><span class="type">boolean</span></span>
184 true if any of the flags are set, false otherwise.
185 </ol>
186
187
188
189 <h3>Usage:</h3>
190 <ul>
191 <pre class="example"><span class="keyword">local</span> sys = <span class="global">require</span> <span class="string">'system'</span>
192<span class="keyword">local</span> flags = sys.<span class="function-name">bitflag</span>(<span class="number">12</span>) <span class="comment">-- b1100
193</span><span class="keyword">local</span> myflags = sys.<span class="function-name">bitflag</span>(<span class="number">7</span>) <span class="comment">-- b0111
194</span><span class="global">print</span>(flags:<span class="function-name">has_any_of</span>(myflags)) <span class="comment">-- true, some bits in myflags are set in flags
195</span><span class="global">print</span>(myflags:<span class="function-name">has_any_of</span>(flags)) <span class="comment">-- true, some bits in flags are set in myflags</span></pre>
196 </ul>
197
198</dd>
199 <dt>
200 <a name = "bitflag:value"></a>
201 <strong>bitflag:value ()</strong>
202 </dt>
203 <dd>
204 Retrieves the numeric value of the bitflag object.
205
206
207
208 <h3>Returns:</h3>
209 <ol>
210
211 <span class="types"><span class="type">number</span></span>
212 the numeric value of the bitflags.
213 </ol>
214
215
216
217 <h3>Usage:</h3>
218 <ul>
219 <pre class="example"><span class="keyword">local</span> sys = <span class="global">require</span> <span class="string">'system'</span>
220<span class="keyword">local</span> flags = sys.<span class="function-name">bitflag</span>() <span class="comment">-- b0000
221</span>flags[<span class="number">0</span>] = <span class="keyword">true</span> <span class="comment">-- b0001
222</span>flags[<span class="number">2</span>] = <span class="keyword">true</span> <span class="comment">-- b0101
223</span><span class="global">print</span>(flags:<span class="function-name">value</span>()) <span class="comment">-- 5</span></pre>
224 </ul>
225
226</dd>
227 <dt>
228 <a name = "system.bitflag"></a>
229 <strong>system.bitflag ([value=0])</strong>
230 </dt>
231 <dd>
232 Creates a new bitflag object from the given value.
233
234
235 <h3>Parameters:</h3>
236 <ul>
237 <li><span class="parameter">value</span>
238 <span class="types"><span class="type">number</span></span>
239 the value to create the bitflag object from.
240 (<em>default</em> 0)
241 </li>
242 </ul>
243
244 <h3>Returns:</h3>
245 <ol>
246
247 <span class="types"><a class="type" href="../classes/bitflags.html#system.bitflag">bitflag</a></span>
248 bitflag object with the given values set.
249 </ol>
250
251
252
253 <h3>Usage:</h3>
254 <ul>
255 <pre class="example"><span class="keyword">local</span> sys = <span class="global">require</span> <span class="string">'system'</span>
256<span class="keyword">local</span> flags = sys.<span class="function-name">bitflag</span>(<span class="number">2</span>) <span class="comment">-- b0010
257</span>
258<span class="comment">-- get state of individual bits
259</span><span class="global">print</span>(flags[<span class="number">0</span>]) <span class="comment">-- false
260</span><span class="global">print</span>(flags[<span class="number">1</span>]) <span class="comment">-- true
261</span>
262<span class="comment">-- set individual bits
263</span>flags[<span class="number">0</span>] = <span class="keyword">true</span> <span class="comment">-- b0011
264</span><span class="global">print</span>(flags:<span class="function-name">value</span>()) <span class="comment">-- 3
265</span><span class="global">print</span>(flags) <span class="comment">-- "bitflags: 3"
266</span>
267<span class="comment">-- adding flags (bitwise OR)
268</span><span class="keyword">local</span> flags1 = sys.<span class="function-name">bitflag</span>(<span class="number">1</span>) <span class="comment">-- b0001
269</span><span class="keyword">local</span> flags2 = sys.<span class="function-name">bitflag</span>(<span class="number">2</span>) <span class="comment">-- b0010
270</span><span class="keyword">local</span> flags3 = flags1 + flags2 <span class="comment">-- b0011
271</span>
272<span class="comment">-- substracting flags (bitwise AND NOT)
273</span><span class="global">print</span>(flags3:<span class="function-name">value</span>()) <span class="comment">-- 3
274</span>flag3 = flag3 - flag3 <span class="comment">-- b0000
275</span><span class="global">print</span>(flags3:<span class="function-name">value</span>()) <span class="comment">-- 0
276</span>
277<span class="comment">-- comparing flags
278</span><span class="keyword">local</span> flags4 = sys.<span class="function-name">bitflag</span>(<span class="number">7</span>) <span class="comment">-- b0111
279</span><span class="keyword">local</span> flags5 = sys.<span class="function-name">bitflag</span>(<span class="number">255</span>) <span class="comment">-- b11111111
280</span><span class="global">print</span>(flags5 ~= flags4) <span class="comment">-- true, not the same flags
281</span><span class="keyword">local</span> flags6 = sys.<span class="function-name">bitflag</span>(<span class="number">7</span>) <span class="comment">-- b0111
282</span><span class="global">print</span>(flags6 == flags4) <span class="comment">-- true, same flags
283</span>
284<span class="comment">-- comparison of subsets
285</span><span class="keyword">local</span> flags7 = sys.<span class="function-name">bitflag</span>(<span class="number">0</span>) <span class="comment">-- b0000
286</span><span class="keyword">local</span> flags8 = sys.<span class="function-name">bitflag</span>(<span class="number">3</span>) <span class="comment">-- b0011
287</span><span class="keyword">local</span> flags9 = sys.<span class="function-name">bitflag</span>(<span class="number">7</span>) <span class="comment">-- b0111
288</span><span class="global">print</span>(flags9:<span class="function-name">has_all_of</span>(flags8)) <span class="comment">-- true, flags8 bits are all set in flags9
289</span><span class="global">print</span>(flags8:<span class="function-name">has_any_of</span>(flags9)) <span class="comment">-- true, some of flags9 bits are set in flags8
290</span><span class="global">print</span>(flags8:<span class="function-name">has_all_of</span>(flags7)) <span class="comment">-- false, flags7 (== 0) is not set in flags8</span></pre>
291 </ul>
292
293</dd>
294</dl>
295
296
297</div> <!-- id="content" -->
298</div> <!-- id="main" -->
299<div id="about">
300<i>generated by <a href="http://github.com/lunarmodules/LDoc">LDoc 1.5.0</a></i>
301<i style="float:right;">Last updated 2024-06-20 23:11:37 </i>
302</div> <!-- id="about" -->
303</div> <!-- id="container" -->
304</body>
305</html>
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>
diff --git a/docs/index.html b/docs/index.html
index cd95fc2..52c93fe 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -27,339 +27,122 @@
27<h1>Lua-System</h1> 27<h1>Lua-System</h1>
28 28
29 29
30<h2>Contents</h2> 30
31<ul>
32<li><a href="#environment_Functions">environment Functions</a></li>
33<li><a href="#random_Functions">random Functions</a></li>
34<li><a href="#term_Functions">term Functions</a></li>
35<li><a href="#time_Functions">time Functions</a></li>
36</ul>
37 31
38 32
39<h2>Modules</h2> 33<h2>Modules</h2>
40<ul class="nowrap"> 34<ul class="nowrap">
41 <li><strong>system</strong></li> 35 <li><a href="modules/system.html">system</a></li>
36</ul>
37<h2>Classes</h2>
38<ul class="nowrap">
39 <li><a href="classes/bitflags.html">bitflags</a></li>
42</ul> 40</ul>
43<h2>Topics</h2> 41<h2>Topics</h2>
44<ul class=""> 42<ul class="">
45 <li><a href="topics/01-introduction.md.html">1. Introduction</a></li> 43 <li><a href="topics/01-introduction.md.html">1. Introduction</a></li>
44 <li><a href="topics/02-development.md.html">2. Development</a></li>
45 <li><a href="topics/03-terminal.md.html">3. Terminal functionality</a></li>
46 <li><a href="topics/CHANGELOG.md.html">CHANGELOG</a></li> 46 <li><a href="topics/CHANGELOG.md.html">CHANGELOG</a></li>
47 <li><a href="topics/LICENSE.md.html">MIT License</a></li> 47 <li><a href="topics/LICENSE.md.html">MIT License</a></li>
48</ul> 48</ul>
49<h2>Examples</h2>
50<ul class="nowrap">
51 <li><a href="examples/compat.lua.html">compat.lua</a></li>
52 <li><a href="examples/flag_debugging.lua.html">flag_debugging.lua</a></li>
53 <li><a href="examples/password_input.lua.html">password_input.lua</a></li>
54 <li><a href="examples/read.lua.html">read.lua</a></li>
55 <li><a href="examples/readline.lua.html">readline.lua</a></li>
56 <li><a href="examples/spinner.lua.html">spinner.lua</a></li>
57 <li><a href="examples/spiral_snake.lua.html">spiral_snake.lua</a></li>
58 <li><a href="examples/terminalsize.lua.html">terminalsize.lua</a></li>
59</ul>
49 60
50</div> 61</div>
51 62
52<div id="content"> 63<div id="content">
53 64
54<h1>Module <code>system</code></h1>
55<p>Platform independent system calls for Lua.</p>
56<p>
57
58</p>
59 65
66 <h2>Platform independent system calls for Lua</h2>
60 67
61<h2><a href="#environment_Functions">environment Functions</a></h2> 68<h2>Modules</h2>
62<table class="function_list"> 69<table class="module_list">
63 <tr> 70 <tr>
64 <td class="name" nowrap><a href="#getenv">getenv (name)</a></td> 71 <td class="name" nowrap><a href="modules/system.html">system</a></td>
65 <td class="summary">Gets the value of an environment variable.</td> 72 <td class="summary">Platform independent system calls for Lua.</td>
66 </tr> 73 </tr>
74</table>
75<h2>Classes</h2>
76<table class="module_list">
67 <tr> 77 <tr>
68 <td class="name" nowrap><a href="#getenvs">getenvs ()</a></td> 78 <td class="name" nowrap><a href="classes/bitflags.html">bitflags</a></td>
69 <td class="summary">Returns a table with all environment variables.</td> 79 <td class="summary">Bitflags module.</td>
70 </tr> 80 </tr>
81</table>
82<h2>Topics</h2>
83<table class="module_list">
71 <tr> 84 <tr>
72 <td class="name" nowrap><a href="#setenv">setenv (name[, value])</a></td> 85 <td class="name" nowrap><a href="topics/01-introduction.md.html">01-introduction.md</a></td>
73 <td class="summary">Sets an environment variable.</td> 86 <td class="summary"></td>
74 </tr> 87 </tr>
75</table>
76<h2><a href="#random_Functions">random Functions</a></h2>
77<table class="function_list">
78 <tr> 88 <tr>
79 <td class="name" nowrap><a href="#random">random ([length=1])</a></td> 89 <td class="name" nowrap><a href="topics/02-development.md.html">02-development.md</a></td>
80 <td class="summary">Generate random bytes.</td> 90 <td class="summary"></td>
81 </tr> 91 </tr>
82</table>
83<h2><a href="#term_Functions">term Functions</a></h2>
84<table class="function_list">
85 <tr> 92 <tr>
86 <td class="name" nowrap><a href="#isatty">isatty (file)</a></td> 93 <td class="name" nowrap><a href="topics/03-terminal.md.html">03-terminal.md</a></td>
87 <td class="summary">Checks if a file-handle is a TTY.</td> 94 <td class="summary"></td>
95 </tr>
96 <tr>
97 <td class="name" nowrap><a href="topics/CHANGELOG.md.html">CHANGELOG.md</a></td>
98 <td class="summary"></td>
99 </tr>
100 <tr>
101 <td class="name" nowrap><a href="topics/LICENSE.md.html">LICENSE.md</a></td>
102 <td class="summary"></td>
88 </tr> 103 </tr>
89</table> 104</table>
90<h2><a href="#time_Functions">time Functions</a></h2> 105<h2>Examples</h2>
91<table class="function_list"> 106<table class="module_list">
107 <tr>
108 <td class="name" nowrap><a href="examples/compat.lua.html">compat.lua</a></td>
109 <td class="summary"></td>
110 </tr>
111 <tr>
112 <td class="name" nowrap><a href="examples/flag_debugging.lua.html">flag_debugging.lua</a></td>
113 <td class="summary"></td>
114 </tr>
115 <tr>
116 <td class="name" nowrap><a href="examples/password_input.lua.html">password_input.lua</a></td>
117 <td class="summary"></td>
118 </tr>
119 <tr>
120 <td class="name" nowrap><a href="examples/read.lua.html">read.lua</a></td>
121 <td class="summary"></td>
122 </tr>
123 <tr>
124 <td class="name" nowrap><a href="examples/readline.lua.html">readline.lua</a></td>
125 <td class="summary"></td>
126 </tr>
92 <tr> 127 <tr>
93 <td class="name" nowrap><a href="#gettime">gettime ()</a></td> 128 <td class="name" nowrap><a href="examples/spinner.lua.html">spinner.lua</a></td>
94 <td class="summary">Get system time.</td> 129 <td class="summary"></td>
95 </tr> 130 </tr>
96 <tr> 131 <tr>
97 <td class="name" nowrap><a href="#monotime">monotime ()</a></td> 132 <td class="name" nowrap><a href="examples/spiral_snake.lua.html">spiral_snake.lua</a></td>
98 <td class="summary">Get monotonic time.</td> 133 <td class="summary"></td>
99 </tr> 134 </tr>
100 <tr> 135 <tr>
101 <td class="name" nowrap><a href="#sleep">sleep (seconds[, precision=16])</a></td> 136 <td class="name" nowrap><a href="examples/terminalsize.lua.html">terminalsize.lua</a></td>
102 <td class="summary">Sleep without a busy loop.</td> 137 <td class="summary"></td>
103 </tr> 138 </tr>
104</table> 139</table>
105 140
106<br/>
107<br/>
108
109
110 <h2 class="section-header "><a name="environment_Functions"></a>environment Functions</h2>
111
112 <dl class="function">
113 <dt>
114 <a name = "getenv"></a>
115 <strong>getenv (name)</strong>
116 </dt>
117 <dd>
118 Gets the value of an environment variable. </p>
119
120<p><strong>NOTE</strong>: Windows has multiple copies of environment variables. For this reason,
121the <a href="index.html#setenv">setenv</a> function will not work with Lua's <a href="https://www.lua.org/manual/5.1/manual.html#pdf-os.getenv">os.getenv</a> on Windows. If you want
122to use <a href="index.html#setenv">setenv</a> then consider patching <a href="https://www.lua.org/manual/5.1/manual.html#pdf-os.getenv">os.getenv</a> with this implementation of <a href="index.html#getenv">getenv</a>.
123
124
125 <h3>Parameters:</h3>
126 <ul>
127 <li><span class="parameter">name</span>
128 <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
129 name of the environment variable
130 </li>
131 </ul>
132
133 <h3>Returns:</h3>
134 <ol>
135
136 <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a> or <span class="type">nil</span></span>
137 value of the environment variable, or nil if the variable is not set
138 </ol>
139
140
141
142
143</dd>
144 <dt>
145 <a name = "getenvs"></a>
146 <strong>getenvs ()</strong>
147 </dt>
148 <dd>
149 Returns a table with all environment variables.
150
151
152
153 <h3>Returns:</h3>
154 <ol>
155
156 <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.5">table</a></span>
157 table with all environment variables and their values
158 </ol>
159
160
161
162
163</dd>
164 <dt>
165 <a name = "setenv"></a>
166 <strong>setenv (name[, value])</strong>
167 </dt>
168 <dd>
169 Sets an environment variable. </p>
170
171<p><strong>NOTE</strong>: Windows has multiple copies of environment variables. For this reason, the
172<a href="index.html#setenv">setenv</a> function will not work with Lua's <a href="https://www.lua.org/manual/5.1/manual.html#pdf-os.getenv">os.getenv</a> on Windows. If you want to use
173it then consider patching <a href="https://www.lua.org/manual/5.1/manual.html#pdf-os.getenv">os.getenv</a> with the implementation of <a href="index.html#getenv">system.getenv</a>.
174
175
176 <h3>Parameters:</h3>
177 <ul>
178 <li><span class="parameter">name</span>
179 <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
180 name of the environment variable
181 </li>
182 <li><span class="parameter">value</span>
183 <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
184 value of the environment variable, if <code>nil</code> the variable will be deleted (on
185Windows, setting an empty string, will also delete the variable)
186 (<em>optional</em>)
187 </li>
188 </ul>
189
190 <h3>Returns:</h3>
191 <ol>
192
193 <span class="types"><span class="type">boolean</span></span>
194 success
195 </ol>
196
197
198
199
200</dd>
201</dl>
202 <h2 class="section-header "><a name="random_Functions"></a>random Functions</h2>
203
204 <dl class="function">
205 <dt>
206 <a name = "random"></a>
207 <strong>random ([length=1])</strong>
208 </dt>
209 <dd>
210 Generate random bytes.
211This uses <code>CryptGenRandom()</code> on Windows, and <code>/dev/urandom</code> on other platforms. It will return the
212requested number of bytes, or an error, never a partial result.
213
214
215 <h3>Parameters:</h3>
216 <ul>
217 <li><span class="parameter">length</span>
218 <span class="types"><span class="type">int</span></span>
219 number of bytes to get
220 (<em>default</em> 1)
221 </li>
222 </ul>
223
224 <h3>Returns:</h3>
225 <ol>
226
227 <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
228 string of random bytes
229 </ol>
230 <h3>Or</h3>
231 <ol>
232 <li>
233 <span class="types"><span class="type">nil</span></span>
234
235
236</li>
237 <li>
238 <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
239 error message</li>
240 </ol>
241
242
243
244
245</dd>
246</dl>
247 <h2 class="section-header "><a name="term_Functions"></a>term Functions</h2>
248
249 <dl class="function">
250 <dt>
251 <a name = "isatty"></a>
252 <strong>isatty (file)</strong>
253 </dt>
254 <dd>
255 Checks if a file-handle is a TTY.
256
257
258 <h3>Parameters:</h3>
259 <ul>
260 <li><span class="parameter">file</span>
261 <span class="types"><span class="type">file</span></span>
262 the file-handle to check
263 </li>
264 </ul>
265
266 <h3>Returns:</h3>
267 <ol>
268
269 <span class="types"><span class="type">boolean</span></span>
270 true if the file is a tty
271 </ol>
272
273
274
275
276</dd>
277</dl>
278 <h2 class="section-header "><a name="time_Functions"></a>time Functions</h2>
279
280 <dl class="function">
281 <dt>
282 <a name = "gettime"></a>
283 <strong>gettime ()</strong>
284 </dt>
285 <dd>
286 Get system time.
287The time is returned as the seconds since the epoch (1 January 1970 00:00:00).
288
289
290
291 <h3>Returns:</h3>
292 <ol>
293
294 <span class="types"><span class="type">number</span></span>
295 seconds (fractional)
296 </ol>
297
298
299
300
301</dd>
302 <dt>
303 <a name = "monotime"></a>
304 <strong>monotime ()</strong>
305 </dt>
306 <dd>
307 Get monotonic time.
308The time is returned as the seconds since system start.
309
310
311
312 <h3>Returns:</h3>
313 <ol>
314
315 <span class="types"><span class="type">number</span></span>
316 seconds (fractional)
317 </ol>
318
319
320
321
322</dd>
323 <dt>
324 <a name = "sleep"></a>
325 <strong>sleep (seconds[, precision=16])</strong>
326 </dt>
327 <dd>
328 Sleep without a busy loop.
329This function will sleep, without doing a busy-loop and wasting CPU cycles.
330
331
332 <h3>Parameters:</h3>
333 <ul>
334 <li><span class="parameter">seconds</span>
335 <span class="types"><span class="type">number</span></span>
336 seconds to sleep (fractional).
337 </li>
338 <li><span class="parameter">precision</span>
339 <span class="types"><span class="type">integer</span></span>
340 minimum stepsize in milliseconds (Windows only, ignored elsewhere)
341 (<em>default</em> 16)
342 </li>
343 </ul>
344
345 <h3>Returns:</h3>
346 <ol>
347
348 <code>true</code> on success, or <code>nil+err</code> on failure
349 </ol>
350
351
352
353
354</dd>
355</dl>
356
357
358</div> <!-- id="content" --> 141</div> <!-- id="content" -->
359</div> <!-- id="main" --> 142</div> <!-- id="main" -->
360<div id="about"> 143<div id="about">
361<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i> 144<i>generated by <a href="http://github.com/lunarmodules/LDoc">LDoc 1.5.0</a></i>
362<i style="float:right;">Last updated 2023-12-15 13:15:09 </i> 145<i style="float:right;">Last updated 2024-06-20 23:11:37 </i>
363</div> <!-- id="about" --> 146</div> <!-- id="about" -->
364</div> <!-- id="container" --> 147</div> <!-- id="container" -->
365</body> 148</body>
diff --git a/docs/modules/system.html b/docs/modules/system.html
new file mode 100644
index 0000000..0423e37
--- /dev/null
+++ b/docs/modules/system.html
@@ -0,0 +1,1418 @@
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<h2>Contents</h2>
35<ul>
36<li><a href="#Fields">Fields</a></li>
37<li><a href="#Environment">Environment </a></li>
38<li><a href="#Random">Random </a></li>
39<li><a href="#Terminal">Terminal </a></li>
40<li><a href="#Time">Time </a></li>
41</ul>
42
43
44<h2>Modules</h2>
45<ul class="nowrap">
46 <li><strong>system</strong></li>
47</ul>
48<h2>Classes</h2>
49<ul class="nowrap">
50 <li><a href="../classes/bitflags.html">bitflags</a></li>
51</ul>
52<h2>Topics</h2>
53<ul class="">
54 <li><a href="../topics/01-introduction.md.html">1. Introduction</a></li>
55 <li><a href="../topics/02-development.md.html">2. Development</a></li>
56 <li><a href="../topics/03-terminal.md.html">3. Terminal functionality</a></li>
57 <li><a href="../topics/CHANGELOG.md.html">CHANGELOG</a></li>
58 <li><a href="../topics/LICENSE.md.html">MIT License</a></li>
59</ul>
60<h2>Examples</h2>
61<ul class="nowrap">
62 <li><a href="../examples/compat.lua.html">compat.lua</a></li>
63 <li><a href="../examples/flag_debugging.lua.html">flag_debugging.lua</a></li>
64 <li><a href="../examples/password_input.lua.html">password_input.lua</a></li>
65 <li><a href="../examples/read.lua.html">read.lua</a></li>
66 <li><a href="../examples/readline.lua.html">readline.lua</a></li>
67 <li><a href="../examples/spinner.lua.html">spinner.lua</a></li>
68 <li><a href="../examples/spiral_snake.lua.html">spiral_snake.lua</a></li>
69 <li><a href="../examples/terminalsize.lua.html">terminalsize.lua</a></li>
70</ul>
71
72</div>
73
74<div id="content">
75
76<h1>Module <code>system</code></h1>
77<p>Platform independent system calls for Lua.</p>
78<p>
79
80</p>
81
82
83<h2><a href="#Fields">Fields</a></h2>
84<table class="function_list">
85 <tr>
86 <td class="name" nowrap><a href="#windows">windows</a></td>
87 <td class="summary">Flag to identify Windows.</td>
88 </tr>
89</table>
90<h2><a href="#Environment">Environment </a></h2>
91<table class="function_list">
92 <tr>
93 <td class="name" nowrap><a href="#getenv">getenv (name)</a></td>
94 <td class="summary">Gets the value of an environment variable.</td>
95 </tr>
96 <tr>
97 <td class="name" nowrap><a href="#getenvs">getenvs ()</a></td>
98 <td class="summary">Returns a table with all environment variables.</td>
99 </tr>
100 <tr>
101 <td class="name" nowrap><a href="#setenv">setenv (name[, value])</a></td>
102 <td class="summary">Sets an environment variable.</td>
103 </tr>
104</table>
105<h2><a href="#Random">Random </a></h2>
106<table class="function_list">
107 <tr>
108 <td class="name" nowrap><a href="#random">random ([length=1])</a></td>
109 <td class="summary">Generate random bytes.</td>
110 </tr>
111</table>
112<h2><a href="#Terminal">Terminal </a></h2>
113<table class="function_list">
114 <tr>
115 <td class="name" nowrap><a href="#CODEPAGE_UTF8">CODEPAGE_UTF8</a></td>
116 <td class="summary">UTF8 codepage.</td>
117 </tr>
118 <tr>
119 <td class="name" nowrap><a href="#_readkey">_readkey ()</a></td>
120 <td class="summary">Reads a key from the console non-blocking.</td>
121 </tr>
122 <tr>
123 <td class="name" nowrap><a href="#autotermrestore">autotermrestore ()</a></td>
124 <td class="summary">Backs up terminal settings and restores them on application exit.</td>
125 </tr>
126 <tr>
127 <td class="name" nowrap><a href="#getconsolecp">getconsolecp ()</a></td>
128 <td class="summary">Gets the current console code page (Windows).</td>
129 </tr>
130 <tr>
131 <td class="name" nowrap><a href="#getconsoleflags">getconsoleflags (file)</a></td>
132 <td class="summary">Gets console flags (Windows).</td>
133 </tr>
134 <tr>
135 <td class="name" nowrap><a href="#getconsoleoutputcp">getconsoleoutputcp ()</a></td>
136 <td class="summary">Gets the current console output code page (Windows).</td>
137 </tr>
138 <tr>
139 <td class="name" nowrap><a href="#getnonblock">getnonblock (fd)</a></td>
140 <td class="summary">Gets non-blocking mode status for a file (Posix).</td>
141 </tr>
142 <tr>
143 <td class="name" nowrap><a href="#isatty">isatty (file)</a></td>
144 <td class="summary">Checks if a file-handle is a TTY.</td>
145 </tr>
146 <tr>
147 <td class="name" nowrap><a href="#listconsoleflags">listconsoleflags (fh)</a></td>
148 <td class="summary">Debug function for console flags (Windows).</td>
149 </tr>
150 <tr>
151 <td class="name" nowrap><a href="#listtermflags">listtermflags (fh)</a></td>
152 <td class="summary">Debug function for terminal flags (Posix).</td>
153 </tr>
154 <tr>
155 <td class="name" nowrap><a href="#readansi">readansi (timeout)</a></td>
156 <td class="summary">Reads a single key, if it is the start of ansi escape sequence then it reads
157 the full sequence.</td>
158 </tr>
159 <tr>
160 <td class="name" nowrap><a href="#readkey">readkey (timeout)</a></td>
161 <td class="summary">Reads a single byte from the console, with a timeout.</td>
162 </tr>
163 <tr>
164 <td class="name" nowrap><a href="#setconsolecp">setconsolecp (cp)</a></td>
165 <td class="summary">Sets the current console code page (Windows).</td>
166 </tr>
167 <tr>
168 <td class="name" nowrap><a href="#setconsoleflags">setconsoleflags (file, bitflags)</a></td>
169 <td class="summary">Sets the console flags (Windows).</td>
170 </tr>
171 <tr>
172 <td class="name" nowrap><a href="#setconsoleoutputcp">setconsoleoutputcp (cp)</a></td>
173 <td class="summary">Sets the current console output code page (Windows).</td>
174 </tr>
175 <tr>
176 <td class="name" nowrap><a href="#setnonblock">setnonblock (fd, make_non_block)</a></td>
177 <td class="summary">Enables or disables non-blocking mode for a file (Posix).</td>
178 </tr>
179 <tr>
180 <td class="name" nowrap><a href="#tcgetattr">tcgetattr (fd)</a></td>
181 <td class="summary">Get termios state (Posix).</td>
182 </tr>
183 <tr>
184 <td class="name" nowrap><a href="#tcsetattr">tcsetattr (fd, actions, termios)</a></td>
185 <td class="summary">Set termios state (Posix).</td>
186 </tr>
187 <tr>
188 <td class="name" nowrap><a href="#termbackup">termbackup ()</a></td>
189 <td class="summary">Returns a backup of terminal settings for stdin/out/err.</td>
190 </tr>
191 <tr>
192 <td class="name" nowrap><a href="#termrestore">termrestore (backup)</a></td>
193 <td class="summary">Restores terminal settings from a backup</td>
194 </tr>
195 <tr>
196 <td class="name" nowrap><a href="#termsize">termsize ()</a></td>
197 <td class="summary">Get the size of the terminal in rows and columns.</td>
198 </tr>
199 <tr>
200 <td class="name" nowrap><a href="#termwrap">termwrap (f)</a></td>
201 <td class="summary">Wraps a function to automatically restore terminal settings upon returning.</td>
202 </tr>
203 <tr>
204 <td class="name" nowrap><a href="#utf8cwidth">utf8cwidth (utf8_char)</a></td>
205 <td class="summary">Get the width of a utf8 character for terminal display.</td>
206 </tr>
207 <tr>
208 <td class="name" nowrap><a href="#utf8swidth">utf8swidth (utf8_string)</a></td>
209 <td class="summary">Get the width of a utf8 string for terminal display.</td>
210 </tr>
211</table>
212<h2><a href="#Time">Time </a></h2>
213<table class="function_list">
214 <tr>
215 <td class="name" nowrap><a href="#gettime">gettime ()</a></td>
216 <td class="summary">Get system time.</td>
217 </tr>
218 <tr>
219 <td class="name" nowrap><a href="#monotime">monotime ()</a></td>
220 <td class="summary">Get monotonic time.</td>
221 </tr>
222 <tr>
223 <td class="name" nowrap><a href="#sleep">sleep (seconds[, precision=16])</a></td>
224 <td class="summary">Sleep without a busy loop.</td>
225 </tr>
226</table>
227
228<br/>
229<br/>
230
231
232 <h2 class="section-header "><a name="Fields"></a>Fields</h2>
233
234 <dl class="function">
235 <dt>
236 <a name = "windows"></a>
237 <strong>windows</strong>
238 </dt>
239 <dd>
240 Flag to identify Windows.
241
242
243 <ul>
244 <li><span class="parameter">windows</span>
245 <code>true</code> if on Windows, <code>false</code> otherwise.
246 </li>
247 </ul>
248
249
250
251
252
253</dd>
254</dl>
255 <h2 class="section-header "><a name="Environment"></a>Environment </h2>
256
257 <dl class="function">
258 <dt>
259 <a name = "getenv"></a>
260 <strong>getenv (name)</strong>
261 </dt>
262 <dd>
263 Gets the value of an environment variable. </p>
264
265<p><strong>NOTE</strong>: Windows has multiple copies of environment variables. For this reason,
266the <a href="../modules/system.html#setenv">setenv</a> function will not work with Lua's <a href="https://www.lua.org/manual/5.4/manual.html#pdf-os.getenv">os.getenv</a> on Windows. If you want
267to use <a href="../modules/system.html#setenv">setenv</a> then consider patching <a href="https://www.lua.org/manual/5.4/manual.html#pdf-os.getenv">os.getenv</a> with this implementation of <a href="../modules/system.html#getenv">getenv</a>.
268
269
270 <h3>Parameters:</h3>
271 <ul>
272 <li><span class="parameter">name</span>
273 <span class="types"><a class="type" href="https://www.lua.org/manual/5.4/manual.html#6.4">string</a></span>
274 name of the environment variable
275 </li>
276 </ul>
277
278 <h3>Returns:</h3>
279 <ol>
280
281 <span class="types"><a class="type" href="https://www.lua.org/manual/5.4/manual.html#6.4">string</a> or <span class="type">nil</span></span>
282 value of the environment variable, or nil if the variable is not set
283 </ol>
284
285
286
287
288</dd>
289 <dt>
290 <a name = "getenvs"></a>
291 <strong>getenvs ()</strong>
292 </dt>
293 <dd>
294 Returns a table with all environment variables.
295
296
297
298 <h3>Returns:</h3>
299 <ol>
300
301 <span class="types"><a class="type" href="https://www.lua.org/manual/5.4/manual.html#6.6">table</a></span>
302 table with all environment variables and their values
303 </ol>
304
305
306
307
308</dd>
309 <dt>
310 <a name = "setenv"></a>
311 <strong>setenv (name[, value])</strong>
312 </dt>
313 <dd>
314 Sets an environment variable. </p>
315
316<p><strong>NOTE</strong>: Windows has multiple copies of environment variables. For this reason, the
317<a href="../modules/system.html#setenv">setenv</a> function will not work with Lua's <a href="https://www.lua.org/manual/5.4/manual.html#pdf-os.getenv">os.getenv</a> on Windows. If you want to use
318it then consider patching <a href="https://www.lua.org/manual/5.4/manual.html#pdf-os.getenv">os.getenv</a> with the implementation of <a href="../modules/system.html#getenv">system.getenv</a>.
319
320
321 <h3>Parameters:</h3>
322 <ul>
323 <li><span class="parameter">name</span>
324 <span class="types"><a class="type" href="https://www.lua.org/manual/5.4/manual.html#6.4">string</a></span>
325 name of the environment variable
326 </li>
327 <li><span class="parameter">value</span>
328 <span class="types"><a class="type" href="https://www.lua.org/manual/5.4/manual.html#6.4">string</a></span>
329 value of the environment variable, if <code>nil</code> the variable will be deleted (on
330Windows, setting an empty string, will also delete the variable)
331 (<em>optional</em>)
332 </li>
333 </ul>
334
335 <h3>Returns:</h3>
336 <ol>
337
338 <span class="types"><span class="type">boolean</span></span>
339 success
340 </ol>
341
342
343
344
345</dd>
346</dl>
347 <h2 class="section-header "><a name="Random"></a>Random </h2>
348
349 <dl class="function">
350 <dt>
351 <a name = "random"></a>
352 <strong>random ([length=1])</strong>
353 </dt>
354 <dd>
355 Generate random bytes.
356This uses <code>CryptGenRandom()</code> on Windows, and <code>/dev/urandom</code> on other platforms. It will return the
357requested number of bytes, or an error, never a partial result.
358
359
360 <h3>Parameters:</h3>
361 <ul>
362 <li><span class="parameter">length</span>
363 <span class="types"><span class="type">int</span></span>
364 number of bytes to get
365 (<em>default</em> 1)
366 </li>
367 </ul>
368
369 <h3>Returns:</h3>
370 <ol>
371
372 <span class="types"><a class="type" href="https://www.lua.org/manual/5.4/manual.html#6.4">string</a></span>
373 string of random bytes
374 </ol>
375 <h3>Or</h3>
376 <ol>
377 <li>
378 <span class="types"><span class="type">nil</span></span>
379
380
381</li>
382 <li>
383 <span class="types"><a class="type" href="https://www.lua.org/manual/5.4/manual.html#6.4">string</a></span>
384 error message</li>
385 </ol>
386
387
388
389
390</dd>
391</dl>
392 <h2 class="section-header has-description"><a name="Terminal"></a>Terminal </h2>
393
394 <div class="section-description">
395 Unix: see https://blog.nelhage.com/2009/12/a-brief-introduction-to-termios-termios3-and-stty/</p>
396
397<p> Windows: see https://learn.microsoft.com/en-us/windows/console/console-reference
398 </div>
399 <dl class="function">
400 <dt>
401 <a name = "CODEPAGE_UTF8"></a>
402 <strong>CODEPAGE_UTF8</strong>
403 </dt>
404 <dd>
405 UTF8 codepage.
406 To be used with <a href="../modules/system.html#setconsoleoutputcp">system.setconsoleoutputcp</a> and <a href="../modules/system.html#setconsolecp">system.setconsolecp</a>.
407
408
409 <ul>
410 <li><span class="parameter">CODEPAGE_UTF8</span>
411 The Windows CodePage for UTF8.
412 </li>
413 </ul>
414
415
416
417
418
419</dd>
420 <dt>
421 <a name = "_readkey"></a>
422 <strong>_readkey ()</strong>
423 </dt>
424 <dd>
425 Reads a key from the console non-blocking. This function should not be called
426directly, but through the <a href="../modules/system.html#readkey">system.readkey</a> or <a href="../modules/system.html#readansi">system.readansi</a> functions. It
427will return the next byte from the input stream, or <code>nil</code> if no key was pressed.</p>
428
429<p>On Posix, <a href="https://www.lua.org/manual/5.4/manual.html#pdf-io.stdin">io.stdin</a> must be set to non-blocking mode using <a href="../modules/system.html#setnonblock">setnonblock</a>
430and canonical mode must be turned off using <a href="../modules/system.html#tcsetattr">tcsetattr</a>,
431before calling this function. Otherwise it will block. No conversions are
432done on Posix, so the byte read is returned as-is.</p>
433
434<p>On Windows this reads a wide character and converts it to UTF-8. Multi-byte
435sequences will be buffered internally and returned one byte at a time.
436
437
438
439 <h3>Returns:</h3>
440 <ol>
441
442 <span class="types"><span class="type">integer</span></span>
443 the byte read from the input stream
444 </ol>
445 <h3>Or</h3>
446 <ol>
447
448 <span class="types"><span class="type">nil</span></span>
449 if no key was pressed
450 </ol>
451 <h3>Or</h3>
452 <ol>
453 <li>
454 <span class="types"><span class="type">nil</span></span>
455 on error</li>
456 <li>
457 <span class="types"><a class="type" href="https://www.lua.org/manual/5.4/manual.html#6.4">string</a></span>
458 error message</li>
459 <li>
460 <span class="types"><span class="type">int</span></span>
461 errnum (on posix)</li>
462 </ol>
463
464
465
466
467</dd>
468 <dt>
469 <a name = "autotermrestore"></a>
470 <strong>autotermrestore ()</strong>
471 </dt>
472 <dd>
473 Backs up terminal settings and restores them on application exit.
474 Calls <a href="../modules/system.html#termbackup">termbackup</a> to back up terminal settings and sets up a GC method to
475 automatically restore them on application exit (also works on Lua 5.1).
476
477
478
479 <h3>Returns:</h3>
480 <ol>
481
482 <span class="types"><span class="type">boolean</span></span>
483 true
484 </ol>
485 <h3>Or</h3>
486 <ol>
487 <li>
488 <span class="types"><span class="type">nil</span></span>
489 if the backup was already created</li>
490 <li>
491 <span class="types"><a class="type" href="https://www.lua.org/manual/5.4/manual.html#6.4">string</a></span>
492 error message</li>
493 </ol>
494
495
496
497
498</dd>
499 <dt>
500 <a name = "getconsolecp"></a>
501 <strong>getconsolecp ()</strong>
502 </dt>
503 <dd>
504 Gets the current console code page (Windows).
505
506
507
508 <h3>Returns:</h3>
509 <ol>
510
511 <span class="types"><span class="type">int</span></span>
512 the current code page (always 65001 on Posix systems)
513 </ol>
514
515
516
517
518</dd>
519 <dt>
520 <a name = "getconsoleflags"></a>
521 <strong>getconsoleflags (file)</strong>
522 </dt>
523 <dd>
524 Gets console flags (Windows).
525The <code>CIF_</code> and <code>COF_</code> constants are available on the module table. Where <code>CIF</code> are the
526input flags (for use with <a href="https://www.lua.org/manual/5.4/manual.html#pdf-io.stdin">io.stdin</a>) and <code>COF</code> are the output flags (for use with
527<a href="https://www.lua.org/manual/5.4/manual.html#pdf-io.stdout">io.stdout</a>/<a href="https://www.lua.org/manual/5.4/manual.html#pdf-io.stderr">io.stderr</a>).</p>
528
529<p><em>Note</em>: See <a href="https://learn.microsoft.com/en-us/windows/console/setconsolemode">setconsolemode documentation</a>
530for more information on the flags.
531
532
533 <h3>Parameters:</h3>
534 <ul>
535 <li><span class="parameter">file</span>
536 <span class="types"><span class="type">file</span></span>
537 file handle to operate on, one of <a href="https://www.lua.org/manual/5.4/manual.html#pdf-io.stdin">io.stdin</a>, <a href="https://www.lua.org/manual/5.4/manual.html#pdf-io.stdout">io.stdout</a>, <a href="https://www.lua.org/manual/5.4/manual.html#pdf-io.stderr">io.stderr</a>
538 </li>
539 </ul>
540
541 <h3>Returns:</h3>
542 <ol>
543
544 <span class="types"><a class="type" href="../classes/bitflags.html#">bitflags</a></span>
545 the current console flags.
546 </ol>
547 <h3>Or</h3>
548 <ol>
549 <li>
550 <span class="types"><span class="type">nil</span></span>
551
552
553</li>
554 <li>
555 <span class="types"><a class="type" href="https://www.lua.org/manual/5.4/manual.html#6.4">string</a></span>
556 error message</li>
557 </ol>
558
559
560
561 <h3>Usage:</h3>
562 <ul>
563 <pre class="example"><span class="keyword">local</span> system = <span class="global">require</span>(<span class="string">'system'</span>)
564
565<span class="keyword">local</span> flags = system.<span class="function-name">getconsoleflags</span>(<span class="global">io</span>.stdout)
566<span class="global">print</span>(<span class="string">"Current stdout flags:"</span>, <span class="global">tostring</span>(flags))
567
568<span class="keyword">if</span> flags:<span class="function-name">has_all_of</span>(system.COF_VIRTUAL_TERMINAL_PROCESSING + system.COF_PROCESSED_OUTPUT) <span class="keyword">then</span>
569 <span class="global">print</span>(<span class="string">"Both flags are set"</span>)
570<span class="keyword">else</span>
571 <span class="global">print</span>(<span class="string">"At least one flag is not set"</span>)
572<span class="keyword">end</span></pre>
573 </ul>
574
575</dd>
576 <dt>
577 <a name = "getconsoleoutputcp"></a>
578 <strong>getconsoleoutputcp ()</strong>
579 </dt>
580 <dd>
581 Gets the current console output code page (Windows).
582
583
584
585 <h3>Returns:</h3>
586 <ol>
587
588 <span class="types"><span class="type">int</span></span>
589 the current code page (always 65001 on Posix systems)
590 </ol>
591
592
593
594
595</dd>
596 <dt>
597 <a name = "getnonblock"></a>
598 <strong>getnonblock (fd)</strong>
599 </dt>
600 <dd>
601 Gets non-blocking mode status for a file (Posix).
602
603
604 <h3>Parameters:</h3>
605 <ul>
606 <li><span class="parameter">fd</span>
607 <span class="types"><span class="type">file</span></span>
608 file handle to operate on, one of <a href="https://www.lua.org/manual/5.4/manual.html#pdf-io.stdin">io.stdin</a>, <a href="https://www.lua.org/manual/5.4/manual.html#pdf-io.stdout">io.stdout</a>, <a href="https://www.lua.org/manual/5.4/manual.html#pdf-io.stderr">io.stderr</a>
609 </li>
610 </ul>
611
612 <h3>Returns:</h3>
613 <ol>
614
615 <span class="types"><span class="type">bool</span></span>
616 <code>true</code> if set to non-blocking, <code>false</code> if not. Always returns <code>false</code> on Windows.
617 </ol>
618 <h3>Or</h3>
619 <ol>
620 <li>
621 <span class="types"><span class="type">nil</span></span>
622
623
624</li>
625 <li>
626 <span class="types"><a class="type" href="https://www.lua.org/manual/5.4/manual.html#6.4">string</a></span>
627 error message</li>
628 <li>
629 <span class="types"><span class="type">int</span></span>
630 errnum</li>
631 </ol>
632
633
634
635
636</dd>
637 <dt>
638 <a name = "isatty"></a>
639 <strong>isatty (file)</strong>
640 </dt>
641 <dd>
642 Checks if a file-handle is a TTY.
643
644
645 <h3>Parameters:</h3>
646 <ul>
647 <li><span class="parameter">file</span>
648 <span class="types"><span class="type">file</span></span>
649 the file-handle to check, one of <a href="https://www.lua.org/manual/5.4/manual.html#pdf-io.stdin">io.stdin</a>, <a href="https://www.lua.org/manual/5.4/manual.html#pdf-io.stdout">io.stdout</a>, <a href="https://www.lua.org/manual/5.4/manual.html#pdf-io.stderr">io.stderr</a>.
650 </li>
651 </ul>
652
653 <h3>Returns:</h3>
654 <ol>
655
656 <span class="types"><span class="type">boolean</span></span>
657 true if the file is a tty
658 </ol>
659
660
661
662 <h3>Usage:</h3>
663 <ul>
664 <pre class="example"><span class="keyword">local</span> system = <span class="global">require</span>(<span class="string">'system'</span>)
665<span class="keyword">if</span> system.<span class="function-name">isatty</span>(<span class="global">io</span>.stdin) <span class="keyword">then</span>
666 <span class="comment">-- enable ANSI coloring etc on Windows, does nothing in Posix.
667</span> <span class="keyword">local</span> flags = system.<span class="function-name">getconsoleflags</span>(<span class="global">io</span>.stdout)
668 system.<span class="function-name">setconsoleflags</span>(<span class="global">io</span>.stdout, flags + sys.COF_VIRTUAL_TERMINAL_PROCESSING)
669<span class="keyword">end</span></pre>
670 </ul>
671
672</dd>
673 <dt>
674 <a name = "listconsoleflags"></a>
675 <strong>listconsoleflags (fh)</strong>
676 </dt>
677 <dd>
678 Debug function for console flags (Windows).
679 Pretty prints the current flags set for the handle.
680
681
682 <h3>Parameters:</h3>
683 <ul>
684 <li><span class="parameter">fh</span>
685 file handle (<a href="https://www.lua.org/manual/5.4/manual.html#pdf-io.stdin">io.stdin</a>, <a href="https://www.lua.org/manual/5.4/manual.html#pdf-io.stdout">io.stdout</a>, <a href="https://www.lua.org/manual/5.4/manual.html#pdf-io.stderr">io.stderr</a>)
686 </li>
687 </ul>
688
689
690
691
692 <h3>Usage:</h3>
693 <ul>
694 <pre class="example"><span class="comment">-- Print the flags for stdin/out/err
695</span>system.<span class="function-name">listconsoleflags</span>(<span class="global">io</span>.stdin)
696system.<span class="function-name">listconsoleflags</span>(<span class="global">io</span>.stdout)
697system.<span class="function-name">listconsoleflags</span>(<span class="global">io</span>.stderr)</pre>
698 </ul>
699
700</dd>
701 <dt>
702 <a name = "listtermflags"></a>
703 <strong>listtermflags (fh)</strong>
704 </dt>
705 <dd>
706 Debug function for terminal flags (Posix).
707 Pretty prints the current flags set for the handle.
708
709
710 <h3>Parameters:</h3>
711 <ul>
712 <li><span class="parameter">fh</span>
713 file handle (<a href="https://www.lua.org/manual/5.4/manual.html#pdf-io.stdin">io.stdin</a>, <a href="https://www.lua.org/manual/5.4/manual.html#pdf-io.stdout">io.stdout</a>, <a href="https://www.lua.org/manual/5.4/manual.html#pdf-io.stderr">io.stderr</a>)
714 </li>
715 </ul>
716
717
718
719
720 <h3>Usage:</h3>
721 <ul>
722 <pre class="example"><span class="comment">-- Print the flags for stdin/out/err
723</span>system.<span class="function-name">listconsoleflags</span>(<span class="global">io</span>.stdin)
724system.<span class="function-name">listconsoleflags</span>(<span class="global">io</span>.stdout)
725system.<span class="function-name">listconsoleflags</span>(<span class="global">io</span>.stderr)</pre>
726 </ul>
727
728</dd>
729 <dt>
730 <a name = "readansi"></a>
731 <strong>readansi (timeout)</strong>
732 </dt>
733 <dd>
734 Reads a single key, if it is the start of ansi escape sequence then it reads
735 the full sequence. The key can be a multi-byte string in case of multibyte UTF-8 character.
736 This function uses <a href="../modules/system.html#readkey">system.readkey</a>, and hence <a href="../modules/system.html#sleep">system.sleep</a> to wait until either a key is
737 available or the timeout is reached.
738 It returns immediately if a key is available or if <code>timeout</code> is less than or equal to <code>0</code>.
739 In case of an ANSI sequence, it will return the full sequence as a string.
740
741
742 <h3>Parameters:</h3>
743 <ul>
744 <li><span class="parameter">timeout</span>
745 <span class="types"><span class="type">number</span></span>
746 the timeout in seconds.
747 </li>
748 </ul>
749
750 <h3>Returns:</h3>
751 <ol>
752 <li>
753 <span class="types"><a class="type" href="https://www.lua.org/manual/5.4/manual.html#6.4">string</a></span>
754 the character that was received (can be multi-byte), or a complete ANSI sequence</li>
755 <li>
756 <span class="types"><a class="type" href="https://www.lua.org/manual/5.4/manual.html#6.4">string</a></span>
757 the type of input: <code>&quot;char&quot;</code> for a single key, <code>&quot;ansi&quot;</code> for an ANSI sequence</li>
758 </ol>
759 <h3>Or</h3>
760 <ol>
761 <li>
762 <span class="types"><span class="type">nil</span></span>
763 in case of an error</li>
764 <li>
765 <span class="types"><a class="type" href="https://www.lua.org/manual/5.4/manual.html#6.4">string</a></span>
766 error message; <code>&quot;timeout&quot;</code> if the timeout was reached.</li>
767 <li>
768 <span class="types"><a class="type" href="https://www.lua.org/manual/5.4/manual.html#6.4">string</a></span>
769 partial result in case of an error while reading a sequence, the sequence so far.</li>
770 </ol>
771
772
773
774
775</dd>
776 <dt>
777 <a name = "readkey"></a>
778 <strong>readkey (timeout)</strong>
779 </dt>
780 <dd>
781 Reads a single byte from the console, with a timeout.
782 This function uses <a href="../modules/system.html#sleep">system.sleep</a> to wait until either a byte is available or the timeout is reached.
783 The sleep period is exponentially backing off, starting at 0.0125 seconds, with a maximum of 0.2 seconds.
784 It returns immediately if a byte is available or if <code>timeout</code> is less than or equal to <code>0</code>.</p>
785
786<p> Using <a href="../modules/system.html#readansi">system.readansi</a> is preferred over this function. Since this function can leave stray/invalid
787 byte-sequences in the input buffer, while <a href="../modules/system.html#readansi">system.readansi</a> reads full ANSI and UTF8 sequences.
788
789
790 <h3>Parameters:</h3>
791 <ul>
792 <li><span class="parameter">timeout</span>
793 <span class="types"><span class="type">number</span></span>
794 the timeout in seconds.
795 </li>
796 </ul>
797
798 <h3>Returns:</h3>
799 <ol>
800
801 <span class="types"><span class="type">byte</span></span>
802 the byte value that was read.
803 </ol>
804 <h3>Or</h3>
805 <ol>
806 <li>
807 <span class="types"><span class="type">nil</span></span>
808 if no key was read</li>
809 <li>
810 <span class="types"><a class="type" href="https://www.lua.org/manual/5.4/manual.html#6.4">string</a></span>
811 error message; <code>&quot;timeout&quot;</code> if the timeout was reached.</li>
812 </ol>
813
814
815
816
817</dd>
818 <dt>
819 <a name = "setconsolecp"></a>
820 <strong>setconsolecp (cp)</strong>
821 </dt>
822 <dd>
823 Sets the current console code page (Windows).
824
825
826 <h3>Parameters:</h3>
827 <ul>
828 <li><span class="parameter">cp</span>
829 <span class="types"><span class="type">int</span></span>
830 the code page to set, use <a href="../modules/system.html#CODEPAGE_UTF8">system.CODEPAGE_UTF8</a> (65001) for UTF-8
831 </li>
832 </ul>
833
834 <h3>Returns:</h3>
835 <ol>
836
837 <span class="types"><span class="type">bool</span></span>
838 <code>true</code> on success (always <code>true</code> on Posix systems)
839 </ol>
840
841
842
843
844</dd>
845 <dt>
846 <a name = "setconsoleflags"></a>
847 <strong>setconsoleflags (file, bitflags)</strong>
848 </dt>
849 <dd>
850 Sets the console flags (Windows).
851The <code>CIF_</code> and <code>COF_</code> constants are available on the module table. Where <code>CIF</code> are the
852input flags (for use with <a href="https://www.lua.org/manual/5.4/manual.html#pdf-io.stdin">io.stdin</a>) and <code>COF</code> are the output flags (for use with
853<a href="https://www.lua.org/manual/5.4/manual.html#pdf-io.stdout">io.stdout</a>/<a href="https://www.lua.org/manual/5.4/manual.html#pdf-io.stderr">io.stderr</a>).</p>
854
855<p>To see flag status and constant names check <a href="../modules/system.html#listconsoleflags">listconsoleflags</a>.</p>
856
857<p>Note: not all combinations of flags are allowed, as some are mutually exclusive or mutually required.
858See <a href="https://learn.microsoft.com/en-us/windows/console/setconsolemode">setconsolemode documentation</a>
859
860
861 <h3>Parameters:</h3>
862 <ul>
863 <li><span class="parameter">file</span>
864 <span class="types"><span class="type">file</span></span>
865 file handle to operate on, one of <a href="https://www.lua.org/manual/5.4/manual.html#pdf-io.stdin">io.stdin</a>, <a href="https://www.lua.org/manual/5.4/manual.html#pdf-io.stdout">io.stdout</a>, <a href="https://www.lua.org/manual/5.4/manual.html#pdf-io.stderr">io.stderr</a>
866 </li>
867 <li><span class="parameter">bitflags</span>
868 <span class="types"><a class="type" href="../classes/bitflags.html#">bitflags</a></span>
869 the flags to set/unset
870 </li>
871 </ul>
872
873 <h3>Returns:</h3>
874 <ol>
875
876 <span class="types"><span class="type">boolean</span></span>
877 <code>true</code> on success
878 </ol>
879 <h3>Or</h3>
880 <ol>
881 <li>
882 <span class="types"><span class="type">nil</span></span>
883
884
885</li>
886 <li>
887 <span class="types"><a class="type" href="https://www.lua.org/manual/5.4/manual.html#6.4">string</a></span>
888 error message</li>
889 </ol>
890
891
892
893 <h3>Usage:</h3>
894 <ul>
895 <pre class="example"><span class="keyword">local</span> system = <span class="global">require</span>(<span class="string">'system'</span>)
896system.<span class="function-name">listconsoleflags</span>(<span class="global">io</span>.stdout) <span class="comment">-- List all the available flags and their current status
897</span>
898<span class="keyword">local</span> flags = system.<span class="function-name">getconsoleflags</span>(<span class="global">io</span>.stdout)
899<span class="global">assert</span>(system.<span class="function-name">setconsoleflags</span>(<span class="global">io</span>.stdout,
900 flags + system.COF_VIRTUAL_TERMINAL_PROCESSING)
901
902system.<span class="function-name">listconsoleflags</span>(<span class="global">io</span>.stdout) <span class="comment">-- List again to check the differences</span></pre>
903 </ul>
904
905</dd>
906 <dt>
907 <a name = "setconsoleoutputcp"></a>
908 <strong>setconsoleoutputcp (cp)</strong>
909 </dt>
910 <dd>
911 Sets the current console output code page (Windows).
912
913
914 <h3>Parameters:</h3>
915 <ul>
916 <li><span class="parameter">cp</span>
917 <span class="types"><span class="type">int</span></span>
918 the code page to set, use <a href="../modules/system.html#CODEPAGE_UTF8">system.CODEPAGE_UTF8</a> (65001) for UTF-8
919 </li>
920 </ul>
921
922 <h3>Returns:</h3>
923 <ol>
924
925 <span class="types"><span class="type">bool</span></span>
926 <code>true</code> on success (always <code>true</code> on Posix systems)
927 </ol>
928
929
930
931
932</dd>
933 <dt>
934 <a name = "setnonblock"></a>
935 <strong>setnonblock (fd, make_non_block)</strong>
936 </dt>
937 <dd>
938 Enables or disables non-blocking mode for a file (Posix).
939
940
941 <h3>Parameters:</h3>
942 <ul>
943 <li><span class="parameter">fd</span>
944 <span class="types"><span class="type">file</span></span>
945 file handle to operate on, one of <a href="https://www.lua.org/manual/5.4/manual.html#pdf-io.stdin">io.stdin</a>, <a href="https://www.lua.org/manual/5.4/manual.html#pdf-io.stdout">io.stdout</a>, <a href="https://www.lua.org/manual/5.4/manual.html#pdf-io.stderr">io.stderr</a>
946 </li>
947 <li><span class="parameter">make_non_block</span>
948 <span class="types"><span class="type">boolean</span></span>
949 a truthy value will enable non-blocking mode, a falsy value will disable it.
950 </li>
951 </ul>
952
953 <h3>Returns:</h3>
954 <ol>
955
956 <span class="types"><span class="type">bool</span></span>
957 <code>true</code>, if successful
958 </ol>
959 <h3>Or</h3>
960 <ol>
961 <li>
962 <span class="types"><span class="type">nil</span></span>
963
964
965</li>
966 <li>
967 <span class="types"><a class="type" href="https://www.lua.org/manual/5.4/manual.html#6.4">string</a></span>
968 error message</li>
969 <li>
970 <span class="types"><span class="type">int</span></span>
971 errnum</li>
972 </ol>
973
974
975 <h3>See also:</h3>
976 <ul>
977 <a href="../modules/system.html#getnonblock">getnonblock</a>
978 </ul>
979
980 <h3>Usage:</h3>
981 <ul>
982 <pre class="example"><span class="keyword">local</span> sys = <span class="global">require</span>(<span class="string">'system'</span>)
983
984<span class="comment">-- set io.stdin to non-blocking mode
985</span><span class="keyword">local</span> old_setting = sys.<span class="function-name">getnonblock</span>(<span class="global">io</span>.stdin)
986sys.<span class="function-name">setnonblock</span>(<span class="global">io</span>.stdin, <span class="keyword">true</span>)
987
988<span class="comment">-- do stuff
989</span>
990<span class="comment">-- restore old setting
991</span>sys.<span class="function-name">setnonblock</span>(<span class="global">io</span>.stdin, old_setting)</pre>
992 </ul>
993
994</dd>
995 <dt>
996 <a name = "tcgetattr"></a>
997 <strong>tcgetattr (fd)</strong>
998 </dt>
999 <dd>
1000
1001<p>Get termios state (Posix).
1002The terminal attributes is a table with the following fields:</p>
1003
1004<ul>
1005 <li><code>iflag</code> input flags</li>
1006 <li><code>oflag</code> output flags</li>
1007 <li><code>lflag</code> local flags</li>
1008 <li><code>cflag</code> control flags</li>
1009 <li><code>ispeed</code> input speed</li>
1010 <li><code>ospeed</code> output speed</li>
1011 <li><code>cc</code> control characters</li>
1012</ul>
1013
1014
1015
1016
1017 <h3>Parameters:</h3>
1018 <ul>
1019 <li><span class="parameter">fd</span>
1020 <span class="types"><span class="type">file</span></span>
1021 file handle to operate on, one of <a href="https://www.lua.org/manual/5.4/manual.html#pdf-io.stdin">io.stdin</a>, <a href="https://www.lua.org/manual/5.4/manual.html#pdf-io.stdout">io.stdout</a>, <a href="https://www.lua.org/manual/5.4/manual.html#pdf-io.stderr">io.stderr</a>
1022 </li>
1023 </ul>
1024
1025 <h3>Returns:</h3>
1026 <ol>
1027
1028 error message if failed
1029 </ol>
1030 <h3>Or</h3>
1031 <ol>
1032
1033 <span class="types"><span class="type">termios</span></span>
1034 terminal attributes, if successful. On Windows the bitflags are all 0, and the <code>cc</code> table is empty.
1035 </ol>
1036 <h3>Or</h3>
1037 <ol>
1038 <li>
1039 <span class="types"><span class="type">nil</span></span>
1040
1041
1042</li>
1043 <li>
1044 <span class="types"><a class="type" href="https://www.lua.org/manual/5.4/manual.html#6.4">string</a></span>
1045 error message</li>
1046 <li>
1047 <span class="types"><span class="type">int</span></span>
1048 errnum</li>
1049 </ol>
1050
1051
1052
1053 <h3>Usage:</h3>
1054 <ul>
1055 <pre class="example"><span class="keyword">local</span> system = <span class="global">require</span>(<span class="string">'system'</span>)
1056
1057<span class="keyword">local</span> status = <span class="global">assert</span>(<span class="function-name">tcgetattr</span>(<span class="global">io</span>.stdin))
1058<span class="keyword">if</span> status.iflag:<span class="function-name">has_all_of</span>(system.I_IGNBRK) <span class="keyword">then</span>
1059 <span class="global">print</span>(<span class="string">"Ignoring break condition"</span>)
1060<span class="keyword">end</span></pre>
1061 </ul>
1062
1063</dd>
1064 <dt>
1065 <a name = "tcsetattr"></a>
1066 <strong>tcsetattr (fd, actions, termios)</strong>
1067 </dt>
1068 <dd>
1069 Set termios state (Posix).
1070This function will set the flags as given.</p>
1071
1072<p>The <code>I_</code>, <code>O_</code>, and <code>L_</code> constants are available on the module table. They are the respective
1073flags for the <code>iflags</code>, <code>oflags</code>, and <code>lflags</code> bitmasks.</p>
1074
1075<p>To see flag status and constant names check <a href="../modules/system.html#listtermflags">listtermflags</a>. For their meaning check
1076<a href="https://www.man7.org/linux/man-pages/man3/termios.3.html">the manpage</a>.</p>
1077
1078<p><em>Note</em>: only <code>iflag</code>, <code>oflag</code>, and <code>lflag</code> are supported at the moment. The other fields are ignored.
1079
1080
1081 <h3>Parameters:</h3>
1082 <ul>
1083 <li><span class="parameter">fd</span>
1084 <span class="types"><span class="type">file</span></span>
1085 file handle to operate on, one of <a href="https://www.lua.org/manual/5.4/manual.html#pdf-io.stdin">io.stdin</a>, <a href="https://www.lua.org/manual/5.4/manual.html#pdf-io.stdout">io.stdout</a>, <a href="https://www.lua.org/manual/5.4/manual.html#pdf-io.stderr">io.stderr</a>
1086 </li>
1087 <li><span class="parameter">actions</span>
1088 <span class="types"><span class="type">integer</span></span>
1089 one of <code>TCSANOW</code>, <code>TCSADRAIN</code>, <code>TCSAFLUSH</code>
1090 </li>
1091 <li><span class="parameter">termios</span> a table with bitflag fields:
1092 <ul>
1093 <li><span class="parameter">iflag</span>
1094 <span class="types"><a class="type" href="../classes/bitflags.html#">bitflags</a></span>
1095 if given will set the input flags
1096 (<em>optional</em>)
1097 </li>
1098 <li><span class="parameter">oflag</span>
1099 <span class="types"><a class="type" href="../classes/bitflags.html#">bitflags</a></span>
1100 if given will set the output flags
1101 (<em>optional</em>)
1102 </li>
1103 <li><span class="parameter">lflag</span>
1104 <span class="types"><a class="type" href="../classes/bitflags.html#">bitflags</a></span>
1105 if given will set the local flags
1106 (<em>optional</em>)
1107 </li>
1108 </li></ul>
1109 </ul>
1110
1111 <h3>Returns:</h3>
1112 <ol>
1113
1114 <span class="types"><span class="type">bool</span></span>
1115 <code>true</code>, if successful. Always returns <code>true</code> on Windows.
1116 </ol>
1117 <h3>Or</h3>
1118 <ol>
1119 <li>
1120 nil</li>
1121 <li>
1122 <span class="types"><a class="type" href="https://www.lua.org/manual/5.4/manual.html#6.4">string</a></span>
1123 error message</li>
1124 <li>
1125 <span class="types"><span class="type">int</span></span>
1126 errnum</li>
1127 </ol>
1128
1129
1130
1131 <h3>Usage:</h3>
1132 <ul>
1133 <pre class="example"><span class="keyword">local</span> system = <span class="global">require</span>(<span class="string">'system'</span>)
1134
1135<span class="keyword">local</span> status = <span class="global">assert</span>(<span class="function-name">tcgetattr</span>(<span class="global">io</span>.stdin))
1136<span class="keyword">if</span> <span class="keyword">not</span> status.lflag:<span class="function-name">has_all_of</span>(system.L_ECHO) <span class="keyword">then</span>
1137 <span class="comment">-- if echo is off, turn echoing newlines on
1138</span> <span class="function-name">tcsetattr</span>(<span class="global">io</span>.stdin, system.TCSANOW, { lflag = status.lflag + system.L_ECHONL }))
1139<span class="keyword">end</span></pre>
1140 </ul>
1141
1142</dd>
1143 <dt>
1144 <a name = "termbackup"></a>
1145 <strong>termbackup ()</strong>
1146 </dt>
1147 <dd>
1148 Returns a backup of terminal settings for stdin/out/err.
1149 Handles terminal/console flags, Windows codepage, and non-block flags on the streams.
1150 Backs up terminal/console flags only if a stream is a tty.
1151
1152
1153
1154 <h3>Returns:</h3>
1155 <ol>
1156
1157 table with backup of terminal settings
1158 </ol>
1159
1160
1161
1162
1163</dd>
1164 <dt>
1165 <a name = "termrestore"></a>
1166 <strong>termrestore (backup)</strong>
1167 </dt>
1168 <dd>
1169 Restores terminal settings from a backup
1170
1171
1172 <h3>Parameters:</h3>
1173 <ul>
1174 <li><span class="parameter">backup</span>
1175 <span class="types"><a class="type" href="https://www.lua.org/manual/5.4/manual.html#6.6">table</a></span>
1176 the backup of terminal settings, see <a href="../modules/system.html#termbackup">termbackup</a>.
1177 </li>
1178 </ul>
1179
1180 <h3>Returns:</h3>
1181 <ol>
1182
1183 <span class="types"><span class="type">boolean</span></span>
1184 true
1185 </ol>
1186
1187
1188
1189
1190</dd>
1191 <dt>
1192 <a name = "termsize"></a>
1193 <strong>termsize ()</strong>
1194 </dt>
1195 <dd>
1196 Get the size of the terminal in rows and columns.
1197
1198
1199
1200 <h3>Returns:</h3>
1201 <ol>
1202 <li>
1203 <span class="types"><span class="type">int</span></span>
1204 the number of rows</li>
1205 <li>
1206 <span class="types"><span class="type">int</span></span>
1207 the number of columns</li>
1208 </ol>
1209 <h3>Or</h3>
1210 <ol>
1211 <li>
1212 <span class="types"><span class="type">nil</span></span>
1213
1214
1215</li>
1216 <li>
1217 <span class="types"><a class="type" href="https://www.lua.org/manual/5.4/manual.html#6.4">string</a></span>
1218 error message</li>
1219 </ol>
1220
1221
1222
1223
1224</dd>
1225 <dt>
1226 <a name = "termwrap"></a>
1227 <strong>termwrap (f)</strong>
1228 </dt>
1229 <dd>
1230 Wraps a function to automatically restore terminal settings upon returning.
1231 Calls <a href="../modules/system.html#termbackup">termbackup</a> before calling the function and <a href="../modules/system.html#termrestore">termrestore</a> after.
1232
1233
1234 <h3>Parameters:</h3>
1235 <ul>
1236 <li><span class="parameter">f</span>
1237 <span class="types"><span class="type">function</span></span>
1238 function to wrap
1239 </li>
1240 </ul>
1241
1242 <h3>Returns:</h3>
1243 <ol>
1244
1245 <span class="types"><span class="type">function</span></span>
1246 wrapped function
1247 </ol>
1248
1249
1250
1251
1252</dd>
1253 <dt>
1254 <a name = "utf8cwidth"></a>
1255 <strong>utf8cwidth (utf8_char)</strong>
1256 </dt>
1257 <dd>
1258 Get the width of a utf8 character for terminal display.
1259
1260
1261 <h3>Parameters:</h3>
1262 <ul>
1263 <li><span class="parameter">utf8_char</span>
1264 <span class="types"><a class="type" href="https://www.lua.org/manual/5.4/manual.html#6.4">string</a></span>
1265 the utf8 character to check, only the width of the first character will be returned
1266 </li>
1267 </ul>
1268
1269 <h3>Returns:</h3>
1270 <ol>
1271
1272 <span class="types"><span class="type">int</span></span>
1273 the display width in columns of the first character in the string (0 for an empty string)
1274 </ol>
1275 <h3>Or</h3>
1276 <ol>
1277 <li>
1278 <span class="types"><span class="type">nil</span></span>
1279
1280
1281</li>
1282 <li>
1283 <span class="types"><a class="type" href="https://www.lua.org/manual/5.4/manual.html#6.4">string</a></span>
1284 error message</li>
1285 </ol>
1286
1287
1288
1289
1290</dd>
1291 <dt>
1292 <a name = "utf8swidth"></a>
1293 <strong>utf8swidth (utf8_string)</strong>
1294 </dt>
1295 <dd>
1296 Get the width of a utf8 string for terminal display.
1297
1298
1299 <h3>Parameters:</h3>
1300 <ul>
1301 <li><span class="parameter">utf8_string</span>
1302 <span class="types"><a class="type" href="https://www.lua.org/manual/5.4/manual.html#6.4">string</a></span>
1303 the utf8 string to check
1304 </li>
1305 </ul>
1306
1307 <h3>Returns:</h3>
1308 <ol>
1309
1310 <span class="types"><span class="type">int</span></span>
1311 the display width of the string in columns (0 for an empty string)
1312 </ol>
1313 <h3>Or</h3>
1314 <ol>
1315 <li>
1316 <span class="types"><span class="type">nil</span></span>
1317
1318
1319</li>
1320 <li>
1321 <span class="types"><a class="type" href="https://www.lua.org/manual/5.4/manual.html#6.4">string</a></span>
1322 error message</li>
1323 </ol>
1324
1325
1326
1327
1328</dd>
1329</dl>
1330 <h2 class="section-header "><a name="Time"></a>Time </h2>
1331
1332 <dl class="function">
1333 <dt>
1334 <a name = "gettime"></a>
1335 <strong>gettime ()</strong>
1336 </dt>
1337 <dd>
1338 Get system time.
1339The time is returned as the seconds since the epoch (1 January 1970 00:00:00).
1340
1341
1342
1343 <h3>Returns:</h3>
1344 <ol>
1345
1346 <span class="types"><span class="type">number</span></span>
1347 seconds (fractional)
1348 </ol>
1349
1350
1351
1352
1353</dd>
1354 <dt>
1355 <a name = "monotime"></a>
1356 <strong>monotime ()</strong>
1357 </dt>
1358 <dd>
1359 Get monotonic time.
1360The time is returned as the seconds since system start.
1361
1362
1363
1364 <h3>Returns:</h3>
1365 <ol>
1366
1367 <span class="types"><span class="type">number</span></span>
1368 seconds (fractional)
1369 </ol>
1370
1371
1372
1373
1374</dd>
1375 <dt>
1376 <a name = "sleep"></a>
1377 <strong>sleep (seconds[, precision=16])</strong>
1378 </dt>
1379 <dd>
1380 Sleep without a busy loop.
1381This function will sleep, without doing a busy-loop and wasting CPU cycles.
1382
1383
1384 <h3>Parameters:</h3>
1385 <ul>
1386 <li><span class="parameter">seconds</span>
1387 <span class="types"><span class="type">number</span></span>
1388 seconds to sleep (fractional).
1389 </li>
1390 <li><span class="parameter">precision</span>
1391 <span class="types"><span class="type">integer</span></span>
1392 minimum stepsize in milliseconds (Windows only, ignored elsewhere)
1393 (<em>default</em> 16)
1394 </li>
1395 </ul>
1396
1397 <h3>Returns:</h3>
1398 <ol>
1399
1400 <code>true</code> on success, or <code>nil+err</code> on failure
1401 </ol>
1402
1403
1404
1405
1406</dd>
1407</dl>
1408
1409
1410</div> <!-- id="content" -->
1411</div> <!-- id="main" -->
1412<div id="about">
1413<i>generated by <a href="http://github.com/lunarmodules/LDoc">LDoc 1.5.0</a></i>
1414<i style="float:right;">Last updated 2024-06-20 23:11:37 </i>
1415</div> <!-- id="about" -->
1416</div> <!-- id="container" -->
1417</body>
1418</html>
diff --git a/docs/topics/01-introduction.md.html b/docs/topics/01-introduction.md.html
index 319b9d5..019f7e4 100644
--- a/docs/topics/01-introduction.md.html
+++ b/docs/topics/01-introduction.md.html
@@ -27,17 +27,38 @@
27<h1>Lua-System</h1> 27<h1>Lua-System</h1>
28 28
29 29
30<ul>
31 <li><a href="../index.html">Index</a></li>
32</ul>
33
30 34
31 35
32<h2>Topics</h2> 36<h2>Topics</h2>
33<ul class=""> 37<ul class="">
34 <li><strong>1. Introduction</strong></li> 38 <li><strong>1. Introduction</strong></li>
39 <li><a href="../topics/02-development.md.html">2. Development</a></li>
40 <li><a href="../topics/03-terminal.md.html">3. Terminal functionality</a></li>
35 <li><a href="../topics/CHANGELOG.md.html">CHANGELOG</a></li> 41 <li><a href="../topics/CHANGELOG.md.html">CHANGELOG</a></li>
36 <li><a href="../topics/LICENSE.md.html">MIT License</a></li> 42 <li><a href="../topics/LICENSE.md.html">MIT License</a></li>
37</ul> 43</ul>
38<h2>Modules</h2> 44<h2>Modules</h2>
39<ul class="nowrap"> 45<ul class="nowrap">
40 <li><a href="../index.html">system</a></li> 46 <li><a href="../modules/system.html">system</a></li>
47</ul>
48<h2>Classes</h2>
49<ul class="nowrap">
50 <li><a href="../classes/bitflags.html">bitflags</a></li>
51</ul>
52<h2>Examples</h2>
53<ul class="nowrap">
54 <li><a href="../examples/compat.lua.html">compat.lua</a></li>
55 <li><a href="../examples/flag_debugging.lua.html">flag_debugging.lua</a></li>
56 <li><a href="../examples/password_input.lua.html">password_input.lua</a></li>
57 <li><a href="../examples/read.lua.html">read.lua</a></li>
58 <li><a href="../examples/readline.lua.html">readline.lua</a></li>
59 <li><a href="../examples/spinner.lua.html">spinner.lua</a></li>
60 <li><a href="../examples/spiral_snake.lua.html">spiral_snake.lua</a></li>
61 <li><a href="../examples/terminalsize.lua.html">terminalsize.lua</a></li>
41</ul> 62</ul>
42 63
43</div> 64</div>
@@ -62,8 +83,8 @@ independence.</p>
62</div> <!-- id="content" --> 83</div> <!-- id="content" -->
63</div> <!-- id="main" --> 84</div> <!-- id="main" -->
64<div id="about"> 85<div id="about">
65<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i> 86<i>generated by <a href="http://github.com/lunarmodules/LDoc">LDoc 1.5.0</a></i>
66<i style="float:right;">Last updated 2023-12-15 13:15:09 </i> 87<i style="float:right;">Last updated 2024-06-20 23:11:37 </i>
67</div> <!-- id="about" --> 88</div> <!-- id="about" -->
68</div> <!-- id="container" --> 89</div> <!-- id="container" -->
69</body> 90</body>
diff --git a/docs/topics/02-development.md.html b/docs/topics/02-development.md.html
new file mode 100644
index 0000000..e911eed
--- /dev/null
+++ b/docs/topics/02-development.md.html
@@ -0,0 +1,91 @@
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>Topics</h2>
37<ul class="">
38 <li><a href="../topics/01-introduction.md.html">1. Introduction</a></li>
39 <li><strong>2. Development</strong></li>
40 <li><a href="../topics/03-terminal.md.html">3. Terminal functionality</a></li>
41 <li><a href="../topics/CHANGELOG.md.html">CHANGELOG</a></li>
42 <li><a href="../topics/LICENSE.md.html">MIT License</a></li>
43</ul>
44<h2>Modules</h2>
45<ul class="nowrap">
46 <li><a href="../modules/system.html">system</a></li>
47</ul>
48<h2>Classes</h2>
49<ul class="nowrap">
50 <li><a href="../classes/bitflags.html">bitflags</a></li>
51</ul>
52<h2>Examples</h2>
53<ul class="nowrap">
54 <li><a href="../examples/compat.lua.html">compat.lua</a></li>
55 <li><a href="../examples/flag_debugging.lua.html">flag_debugging.lua</a></li>
56 <li><a href="../examples/password_input.lua.html">password_input.lua</a></li>
57 <li><a href="../examples/read.lua.html">read.lua</a></li>
58 <li><a href="../examples/readline.lua.html">readline.lua</a></li>
59 <li><a href="../examples/spinner.lua.html">spinner.lua</a></li>
60 <li><a href="../examples/spiral_snake.lua.html">spiral_snake.lua</a></li>
61 <li><a href="../examples/terminalsize.lua.html">terminalsize.lua</a></li>
62</ul>
63
64</div>
65
66<div id="content">
67
68
69<h1>2. Development</h1>
70
71<p>Some tests cannot be run in CI becasue they test system specifics that
72simply do not exist in a CI environment. An example is the <code>isatty</code> function
73Which cannot be set to return a truthy value in CI.</p>
74
75<p>The tests concerned are all labelled with <code>#manual</code>. And in CI they will
76be skipped because <code>--exclude-tags=manual</code> is being passed to the
77<code>busted</code> command line.</p>
78
79<p>Hence if tests like this are being added, then please ensure the tests
80pass locally, and do not rely on CI only.</p>
81
82
83</div> <!-- id="content" -->
84</div> <!-- id="main" -->
85<div id="about">
86<i>generated by <a href="http://github.com/lunarmodules/LDoc">LDoc 1.5.0</a></i>
87<i style="float:right;">Last updated 2024-06-20 23:11:37 </i>
88</div> <!-- id="about" -->
89</div> <!-- id="container" -->
90</body>
91</html>
diff --git a/docs/topics/03-terminal.md.html b/docs/topics/03-terminal.md.html
new file mode 100644
index 0000000..3e7e548
--- /dev/null
+++ b/docs/topics/03-terminal.md.html
@@ -0,0 +1,225 @@
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<h2>Contents</h2>
35<ul>
36<li><a href="#3_1_Backup_and_Restore_terminal_settings">3.1 Backup and Restore terminal settings </a></li>
37<li><a href="#3_1_Terminal_ANSI_sequences">3.1 Terminal ANSI sequences </a></li>
38<li><a href="#3_2_UTF_8_in_output_and_display_width">3.2 UTF-8 in/output and display width </a></li>
39<li><a href="#3_3_reading_keyboard_input">3.3 reading keyboard input </a></li>
40</ul>
41
42
43<h2>Topics</h2>
44<ul class="">
45 <li><a href="../topics/01-introduction.md.html">1. Introduction</a></li>
46 <li><a href="../topics/02-development.md.html">2. Development</a></li>
47 <li><strong>3. Terminal functionality</strong></li>
48 <li><a href="../topics/CHANGELOG.md.html">CHANGELOG</a></li>
49 <li><a href="../topics/LICENSE.md.html">MIT License</a></li>
50</ul>
51<h2>Modules</h2>
52<ul class="nowrap">
53 <li><a href="../modules/system.html">system</a></li>
54</ul>
55<h2>Classes</h2>
56<ul class="nowrap">
57 <li><a href="../classes/bitflags.html">bitflags</a></li>
58</ul>
59<h2>Examples</h2>
60<ul class="nowrap">
61 <li><a href="../examples/compat.lua.html">compat.lua</a></li>
62 <li><a href="../examples/flag_debugging.lua.html">flag_debugging.lua</a></li>
63 <li><a href="../examples/password_input.lua.html">password_input.lua</a></li>
64 <li><a href="../examples/read.lua.html">read.lua</a></li>
65 <li><a href="../examples/readline.lua.html">readline.lua</a></li>
66 <li><a href="../examples/spinner.lua.html">spinner.lua</a></li>
67 <li><a href="../examples/spiral_snake.lua.html">spiral_snake.lua</a></li>
68 <li><a href="../examples/terminalsize.lua.html">terminalsize.lua</a></li>
69</ul>
70
71</div>
72
73<div id="content">
74
75
76<h1>3. Terminal functionality</h1>
77
78<p>Terminals are fundamentally different on Windows and Posix. So even though
79<code>luasystem</code> provides primitives to manipulate both the Windows and Posix terminals,
80the user will still have to write platform specific code.</p>
81
82<p>To mitigate this a little, all functions are available on all platforms. They just
83will be a no-op if invoked on another platform. This means that no platform specific
84branching is required (but still possible) in user code. The user must simply set
85up both platforms to make it work.</p>
86
87<p><a name="3_1_Backup_and_Restore_terminal_settings"></a></p>
88<h2>3.1 Backup and Restore terminal settings</h2>
89
90<p>Since there are a myriad of settings available;</p>
91
92<ul>
93 <li><a href="../modules/system.html#setconsoleflags">system.setconsoleflags</a> (Windows)</li>
94 <li><a href="../modules/system.html#setconsolecp">system.setconsolecp</a> (Windows)</li>
95 <li><a href="../modules/system.html#setconsoleoutputcp">system.setconsoleoutputcp</a> (Windows)</li>
96 <li><a href="../modules/system.html#setnonblock">system.setnonblock</a> (Posix)</li>
97 <li><a href="../modules/system.html#tcsetattr">system.tcsetattr</a> (Posix)</li>
98</ul>
99
100<p>Some helper functions are available to backup and restore them all at once.
101See <code>termbackup</code>, <code>termrestore</code>, <code>autotermrestore</code> and <code>termwrap</code>.</p>
102
103
104<p><a name="3_1_Terminal_ANSI_sequences"></a></p>
105<h2>3.1 Terminal ANSI sequences</h2>
106
107<p>Windows is catching up with this. In Windows 10 (since 2019), the Windows Terminal application (not to be
108mistaken for the <code>cmd</code> console application) supports ANSI sequences. However this
109might not be enabled by default.</p>
110
111<p>ANSI processing can be set up both on the input (key sequences, reading cursor position)
112as well as on the output (setting colors and cursor shapes).</p>
113
114<p>To enable it use <a href="../modules/system.html#setconsoleflags">system.setconsoleflags</a> like this:</p>
115
116
117<pre>
118<span class="comment">-- setup Windows console to handle ANSI processing on output
119</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)
120sys.<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)
121
122<span class="comment">-- setup Windows console to handle ANSI processing on input
123</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_VIRTUAL_TERMINAL_INPUT)
124</pre>
125
126<p><a name="3_2_UTF_8_in_output_and_display_width"></a></p>
127<h2>3.2 UTF-8 in/output and display width</h2>
128
129<h3>3.2.1 UTF-8 in/output</h3>
130
131<p>Where (most) Posix systems use UTF-8 by default, Windows internally uses UTF-16. More
132recent versions of Lua also have UTF-8 support. So <code>luasystem</code> also focusses on UTF-8.</p>
133
134<p>On Windows UTF-8 output can be enabled by setting the output codepage like this:</p>
135
136
137<pre>
138<span class="comment">-- setup Windows output codepage to UTF-8
139</span>sys.<span class="function-name">setconsoleoutputcp</span>(sys.CODEPAGE_UTF8)
140</pre>
141
142<p>Terminal input is handled by the <a href="https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/getchar-getwchar"><code>_getwchar()</code></a> function on Windows which returns
143UTF-16 surrogate pairs. <code>luasystem</code> will automatically convert those to UTF-8.
144So when using <code>readkey</code> or <code>readansi</code> to read keyboard input no additional changes
145are required.</p>
146
147<h3>3.2.2 UTF-8 display width</h3>
148
149<p>Typical western characters and symbols are single width characters and will use only
150a single column when displayed on a terminal. However many characters from other
151languages/cultures or emojis require 2 columns for display.</p>
152
153<p>Typically the <code>wcwidth</code> function is used on Posix to check the number of columns
154required for display. However since Windows doesn't provide this functionality a
155custom implementation is included based on <a href="http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c">the work by Markus Kuhn</a>.</p>
156
157<p>2 functions are provided, <a href="../modules/system.html#utf8cwidth">system.utf8cwidth</a> for a single character, and <a href="../modules/system.html#utf8swidth">system.utf8swidth</a> for
158a string. When writing terminal applications the display width is relevant to
159positioning the cursor properly. For an example see the <a href="../examples/readline.lua.html"><code>examples/readline.lua</code></a> file.</p>
160
161
162<p><a name="3_3_reading_keyboard_input"></a></p>
163<h2>3.3 reading keyboard input</h2>
164
165<h3>3.3.1 Non-blocking</h3>
166
167<p>There are 2 functions for keyboard input (actually 3, if taking <a href="../modules/system.html#_readkey">system._readkey</a> into
168account): <code>readkey</code> and <code>readansi</code>.</p>
169
170<p><code>readkey</code> is a low level function and should preferably not be used, it returns
171a byte at a time, and hence can leave stray/invalid byte sequences in the buffer if
172only the start of a UTF-8 or ANSI sequence is consumed.</p>
173
174<p>The preferred way is to use <code>readansi</code> which will parse and return entire characters in
175single or multiple bytes, or a full ANSI sequence.</p>
176
177<p>On Windows the input is read using <a href="https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/getchar-getwchar"><code>_getwchar()</code></a> which bypasses the terminal and reads
178the input directly from the keyboard buffer. This means however that the character is
179also not being echoed to the terminal (independent of the echo settings used with
180<a href="../modules/system.html#setconsoleflags">system.setconsoleflags</a>).</p>
181
182<p>On Posix the traditional file approach is used, which:</p>
183
184<ul>
185 <li>is blocking by default</li>
186 <li>echoes input to the terminal</li>
187 <li>requires enter to be pressed to pass the input (canonical mode)</li>
188</ul>
189
190<p>To use non-blocking input here's how to set it up:</p>
191
192
193<pre>
194<span class="comment">-- setup Windows console to disable echo and line input (not required since _getwchar is used, just for consistency)
195</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)
196
197<span class="comment">-- setup Posix by disabling echo, canonical mode, and making non-blocking
198</span><span class="keyword">local</span> of_attr = sys.<span class="function-name">tcgetattr</span>(<span class="global">io</span>.stdin)
199sys.<span class="function-name">tcsetattr</span>(<span class="global">io</span>.stdin, sys.TCSANOW, {
200 lflag = of_attr.lflag - sys.L_ICANON - sys.L_ECHO,
201})
202sys.<span class="function-name">setnonblock</span>(<span class="global">io</span>.stdin, <span class="keyword">true</span>)
203</pre>
204
205<p>Both functions require a timeout to be provided which allows for proper asynchronous
206code to be written. Since the underlying sleep method used is <a href="../modules/system.html#sleep">system.sleep</a>, just patching
207that function with a coroutine based yielding one should be all that is needed to make
208the result work with asynchroneous coroutine schedulers.</p>
209
210<h3>3.3.2 Blocking input</h3>
211
212<p>When using traditional input method like <code>io.stdin:read()</code> (which is blocking) the echo
213and newline properties should be set on Windows similar to Posix.
214For an example see <a href="../examples/password_input.lua.html"><code>examples/password_input.lua</code></a>.</p>
215
216
217</div> <!-- id="content" -->
218</div> <!-- id="main" -->
219<div id="about">
220<i>generated by <a href="http://github.com/lunarmodules/LDoc">LDoc 1.5.0</a></i>
221<i style="float:right;">Last updated 2024-06-20 23:11:37 </i>
222</div> <!-- id="about" -->
223</div> <!-- id="container" -->
224</body>
225</html>
diff --git a/docs/topics/CHANGELOG.md.html b/docs/topics/CHANGELOG.md.html
index 4e656c7..da8ddde 100644
--- a/docs/topics/CHANGELOG.md.html
+++ b/docs/topics/CHANGELOG.md.html
@@ -27,6 +27,10 @@
27<h1>Lua-System</h1> 27<h1>Lua-System</h1>
28 28
29 29
30<ul>
31 <li><a href="../index.html">Index</a></li>
32</ul>
33
30<h2>Contents</h2> 34<h2>Contents</h2>
31<ul> 35<ul>
32<li><a href="#Versioning">Versioning </a></li> 36<li><a href="#Versioning">Versioning </a></li>
@@ -37,12 +41,29 @@
37<h2>Topics</h2> 41<h2>Topics</h2>
38<ul class=""> 42<ul class="">
39 <li><a href="../topics/01-introduction.md.html">1. Introduction</a></li> 43 <li><a href="../topics/01-introduction.md.html">1. Introduction</a></li>
44 <li><a href="../topics/02-development.md.html">2. Development</a></li>
45 <li><a href="../topics/03-terminal.md.html">3. Terminal functionality</a></li>
40 <li><strong>CHANGELOG</strong></li> 46 <li><strong>CHANGELOG</strong></li>
41 <li><a href="../topics/LICENSE.md.html">MIT License</a></li> 47 <li><a href="../topics/LICENSE.md.html">MIT License</a></li>
42</ul> 48</ul>
43<h2>Modules</h2> 49<h2>Modules</h2>
44<ul class="nowrap"> 50<ul class="nowrap">
45 <li><a href="../index.html">system</a></li> 51 <li><a href="../modules/system.html">system</a></li>
52</ul>
53<h2>Classes</h2>
54<ul class="nowrap">
55 <li><a href="../classes/bitflags.html">bitflags</a></li>
56</ul>
57<h2>Examples</h2>
58<ul class="nowrap">
59 <li><a href="../examples/compat.lua.html">compat.lua</a></li>
60 <li><a href="../examples/flag_debugging.lua.html">flag_debugging.lua</a></li>
61 <li><a href="../examples/password_input.lua.html">password_input.lua</a></li>
62 <li><a href="../examples/read.lua.html">read.lua</a></li>
63 <li><a href="../examples/readline.lua.html">readline.lua</a></li>
64 <li><a href="../examples/spinner.lua.html">spinner.lua</a></li>
65 <li><a href="../examples/spiral_snake.lua.html">spiral_snake.lua</a></li>
66 <li><a href="../examples/terminalsize.lua.html">terminalsize.lua</a></li>
46</ul> 67</ul>
47 68
48</div> 69</div>
@@ -86,15 +107,31 @@
86<p><a name="Version_history"></a></p> 107<p><a name="Version_history"></a></p>
87<h2>Version history</h2> 108<h2>Version history</h2>
88 109
110<h3>Version 0.4.0, released 20-Jun-2024</h3>
111
112<ul>
113 <li>Feat: <code>getconsoleflags</code> and <code>setconsoleflags</code> for getting/setting the current console configuration flags on Windows</li>
114 <li>Feat: <code>getconsolecp</code> and <code>setconsolecp</code> for getting/setting the console codepage on Windows</li>
115 <li>Feat: <code>getconsoleoutputcp</code> and <code>setconsoleoutputcp</code> for getting/setting the console output codepage on Windows</li>
116 <li>Feat: <code>tcgetattr</code> and <code>tcsetattr</code> for getting/setting the current console configuration flags on Posix</li>
117 <li>Feat: <code>getnonblock</code> and <code>setnonblock</code> for getting/setting the non-blocking flag on Posix</li>
118 <li>Feat: <a href="../classes/bitflags.html#">bitflags</a>: a support feature for the above flag type controls to facilitate bit manipulation without resorting to binary operations (to also support PuC Lua 5.1)</li>
119 <li>Feat: <code>readkey</code> reads a keyboard input from <code>stdin</code> in a non-blocking way (utf8, also on Windows)</li>
120 <li>Feat: <code>readansi</code> reads a keyboard input from <code>stdin</code> in a non-blocking way, parses ansi and utf8 sequences</li>
121 <li>Feat: <code>termsize</code> gets the current terminal size in rows and columns</li>
122 <li>Feat: <code>utf8cwidth</code> and <code>utf8swidth</code> for getting the display width (in columns) of respectively a single utf8 character, or a utf8 string</li>
123 <li>Feat: helpers; <code>termbackup</code>, <code>termrestore</code>, <code>autotermrestore</code>, and <code>termwrap</code> for managing the many terminal settings on all platforms.</li>
124</ul>
125
89<h3>Version 0.3.0, released 15-Dec-2023</h3> 126<h3>Version 0.3.0, released 15-Dec-2023</h3>
90 127
91<ul> 128<ul>
92 <li>Feat: on Windows <a href="../index.html#sleep">sleep</a> now has a precision parameter</li> 129 <li>Feat: on Windows <code>sleep</code> now has a precision parameter</li>
93 <li>Feat: <a href="../index.html#setenv">setenv</a> added to set environment variables.</li> 130 <li>Feat: <code>setenv</code> added to set environment variables.</li>
94 <li>Feat: <a href="../index.html#getenvs">getenvs</a> added to list environment variables.</li> 131 <li>Feat: <code>getenvs</code> added to list environment variables.</li>
95 <li>Feat: <a href="../index.html#getenv">getenv</a> added to get environment variable previously set (Windows).</li> 132 <li>Feat: <code>getenv</code> added to get environment variable previously set (Windows).</li>
96 <li>Feat: <a href="../index.html#random">random</a> added to return high-quality random bytes</li> 133 <li>Feat: <code>random</code> added to return high-quality random bytes</li>
97 <li>Feat: <a href="../index.html#isatty">isatty</a> added to check if a file-handle is a tty</li> 134 <li>Feat: <code>isatty</code> added to check if a file-handle is a tty</li>
98</ul> 135</ul>
99 136
100<h3>Version 0.2.1, released 02-Oct-2016</h3> 137<h3>Version 0.2.1, released 02-Oct-2016</h3>
@@ -113,8 +150,8 @@
113</div> <!-- id="content" --> 150</div> <!-- id="content" -->
114</div> <!-- id="main" --> 151</div> <!-- id="main" -->
115<div id="about"> 152<div id="about">
116<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i> 153<i>generated by <a href="http://github.com/lunarmodules/LDoc">LDoc 1.5.0</a></i>
117<i style="float:right;">Last updated 2023-12-15 13:15:09 </i> 154<i style="float:right;">Last updated 2024-06-20 23:11:37 </i>
118</div> <!-- id="about" --> 155</div> <!-- id="about" -->
119</div> <!-- id="container" --> 156</div> <!-- id="container" -->
120</body> 157</body>
diff --git a/docs/topics/LICENSE.md.html b/docs/topics/LICENSE.md.html
index de3eeff..9866af5 100644
--- a/docs/topics/LICENSE.md.html
+++ b/docs/topics/LICENSE.md.html
@@ -27,17 +27,38 @@
27<h1>Lua-System</h1> 27<h1>Lua-System</h1>
28 28
29 29
30<ul>
31 <li><a href="../index.html">Index</a></li>
32</ul>
33
30 34
31 35
32<h2>Topics</h2> 36<h2>Topics</h2>
33<ul class=""> 37<ul class="">
34 <li><a href="../topics/01-introduction.md.html">1. Introduction</a></li> 38 <li><a href="../topics/01-introduction.md.html">1. Introduction</a></li>
39 <li><a href="../topics/02-development.md.html">2. Development</a></li>
40 <li><a href="../topics/03-terminal.md.html">3. Terminal functionality</a></li>
35 <li><a href="../topics/CHANGELOG.md.html">CHANGELOG</a></li> 41 <li><a href="../topics/CHANGELOG.md.html">CHANGELOG</a></li>
36 <li><strong>MIT License</strong></li> 42 <li><strong>MIT License</strong></li>
37</ul> 43</ul>
38<h2>Modules</h2> 44<h2>Modules</h2>
39<ul class="nowrap"> 45<ul class="nowrap">
40 <li><a href="../index.html">system</a></li> 46 <li><a href="../modules/system.html">system</a></li>
47</ul>
48<h2>Classes</h2>
49<ul class="nowrap">
50 <li><a href="../classes/bitflags.html">bitflags</a></li>
51</ul>
52<h2>Examples</h2>
53<ul class="nowrap">
54 <li><a href="../examples/compat.lua.html">compat.lua</a></li>
55 <li><a href="../examples/flag_debugging.lua.html">flag_debugging.lua</a></li>
56 <li><a href="../examples/password_input.lua.html">password_input.lua</a></li>
57 <li><a href="../examples/read.lua.html">read.lua</a></li>
58 <li><a href="../examples/readline.lua.html">readline.lua</a></li>
59 <li><a href="../examples/spinner.lua.html">spinner.lua</a></li>
60 <li><a href="../examples/spiral_snake.lua.html">spiral_snake.lua</a></li>
61 <li><a href="../examples/terminalsize.lua.html">terminalsize.lua</a></li>
41</ul> 62</ul>
42 63
43</div> 64</div>
@@ -47,7 +68,7 @@
47 68
48<h1>MIT License</h1> 69<h1>MIT License</h1>
49 70
50<h3>Copyright (c) 2016-2023 Oscar Lim</h3> 71<h3>Copyright (c) 2016-2024 Oscar Lim</h3>
51 72
52<p>Permission is hereby granted, free of charge, to any person obtaining a copy of 73<p>Permission is hereby granted, free of charge, to any person obtaining a copy of
53this software and associated documentation files (the "Software"), to deal in 74this software and associated documentation files (the "Software"), to deal in
@@ -71,8 +92,8 @@ SOFTWARE.</p>
71</div> <!-- id="content" --> 92</div> <!-- id="content" -->
72</div> <!-- id="main" --> 93</div> <!-- id="main" -->
73<div id="about"> 94<div id="about">
74<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i> 95<i>generated by <a href="http://github.com/lunarmodules/LDoc">LDoc 1.5.0</a></i>
75<i style="float:right;">Last updated 2023-12-15 13:15:09 </i> 96<i style="float:right;">Last updated 2024-06-20 23:11:37 </i>
76</div> <!-- id="about" --> 97</div> <!-- id="about" -->
77</div> <!-- id="container" --> 98</div> <!-- id="container" -->
78</body> 99</body>
diff --git a/rockspecs/luasystem-0.4.0-1.rockspec b/rockspecs/luasystem-0.4.0-1.rockspec
new file mode 100644
index 0000000..d35565d
--- /dev/null
+++ b/rockspecs/luasystem-0.4.0-1.rockspec
@@ -0,0 +1,85 @@
1local package_name = "luasystem"
2local package_version = "0.4.0"
3local rockspec_revision = "1"
4local github_account_name = "lunarmodules"
5local github_repo_name = "luasystem"
6
7
8package = package_name
9version = package_version.."-"..rockspec_revision
10
11source = {
12 url = "git+https://github.com/"..github_account_name.."/"..github_repo_name..".git",
13 branch = (package_version == "scm") and "master" or nil,
14 tag = (package_version ~= "scm") and "v"..package_version or nil,
15}
16
17description = {
18 summary = 'Platform independent system calls for Lua.',
19 detailed = [[
20 Adds a Lua API for making platform independent system calls.
21 ]],
22 license = 'MIT <http://opensource.org/licenses/MIT>',
23 homepage = "https://github.com/"..github_account_name.."/"..github_repo_name,
24}
25
26dependencies = {
27 'lua >= 5.1',
28}
29
30local function make_platform(plat)
31 local defines = {
32 linux = { },
33 unix = { },
34 macosx = { },
35 win32 = { "WINVER=0x0600", "_WIN32_WINNT=0x0600" },
36 mingw32 = { "WINVER=0x0600", "_WIN32_WINNT=0x0600" },
37 }
38 local libraries = {
39 linux = { "rt" },
40 unix = { },
41 macosx = { },
42 win32 = { "advapi32", "winmm" },
43 mingw32 = { },
44 }
45 local libdirs = {
46 linux = nil,
47 unix = nil,
48 macosx = nil,
49 win32 = nil,
50 mingw32 = { },
51 }
52 return {
53 modules = {
54 ['system.core'] = {
55 sources = {
56 'src/core.c',
57 'src/compat.c',
58 'src/time.c',
59 'src/environment.c',
60 'src/random.c',
61 'src/term.c',
62 'src/bitflags.c',
63 'src/wcwidth.c',
64 },
65 defines = defines[plat],
66 libraries = libraries[plat],
67 libdirs = libdirs[plat],
68 },
69 },
70 }
71end
72
73build = {
74 type = 'builtin',
75 platforms = {
76 linux = make_platform('linux'),
77 unix = make_platform('unix'),
78 macosx = make_platform('macosx'),
79 win32 = make_platform('win32'),
80 mingw32 = make_platform('mingw32'),
81 },
82 modules = {
83 ['system.init'] = 'system/init.lua',
84 },
85}
diff --git a/src/core.c b/src/core.c
index d233ecc..24764c5 100644
--- a/src/core.c
+++ b/src/core.c
@@ -4,7 +4,7 @@
4#include <lua.h> 4#include <lua.h>
5#include <lauxlib.h> 5#include <lauxlib.h>
6 6
7#define LUASYSTEM_VERSION "LuaSystem 0.3.0" 7#define LUASYSTEM_VERSION "LuaSystem 0.4.0"
8 8
9#ifdef _WIN32 9#ifdef _WIN32
10#define LUAEXPORT __declspec(dllexport) 10#define LUAEXPORT __declspec(dllexport)
@@ -26,6 +26,9 @@ LUAEXPORT int luaopen_system_core(lua_State *L) {
26 lua_pushstring(L, "_VERSION"); 26 lua_pushstring(L, "_VERSION");
27 lua_pushstring(L, LUASYSTEM_VERSION); 27 lua_pushstring(L, LUASYSTEM_VERSION);
28 lua_rawset(L, -3); 28 lua_rawset(L, -3);
29
30/// Flag to identify Windows.
31// @field windows `true` if on Windows, `false` otherwise.
29 lua_pushstring(L, "windows"); 32 lua_pushstring(L, "windows");
30#ifdef _WIN32 33#ifdef _WIN32
31 lua_pushboolean(L, 1); 34 lua_pushboolean(L, 1);