-
Notifications
You must be signed in to change notification settings - Fork 108
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Use more auxiliary functions, showing the record being passed in as an argument and out as a return * Returning a number from `return main()` does not do what one would expect (it's not equivalent to `os.exit`) * Do not reference snippets of the code itself in the markdown, makes it harder to maintain in sync * Uppercase-convert the input as a trivial example of data transformation between input and output * Use more descriptive variable/field names instead of comments * Do not use `""` as a sentinel value, as it is less idiomatic for Lua
- Loading branch information
Showing
3 changed files
with
173 additions
and
126 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,68 +1,99 @@ | ||
-- files/src/main.tl | ||
-- Read content from STDIN or file; write content to STDOUT or file. | ||
-- | ||
-- build: cyan build | ||
-- | ||
-- usage: lua files.lua [-i <file>] [-o <file>] | ||
-- | ||
-- Reads content from STDIN or file; | ||
-- writes content in uppercase to STDOUT or file. | ||
------------------------------------------------------------------------------- | ||
|
||
-- record to hold file handles | ||
local type Handles = record | ||
i: FILE -- input | ||
o: FILE -- output | ||
local record Handles | ||
input: FILE | ||
output: FILE | ||
end | ||
|
||
-- a simple command-line parser | ||
local function parse_arguments(args: {string}): string, string | ||
local i_name, o_name: string, string | ||
local err: string | ||
local i = 1 | ||
while i <= #args do | ||
local a, b = args[i], args[i+1] | ||
if a == "-i" then | ||
if not b then | ||
err = "-i name?" | ||
else | ||
i_name = b | ||
i = i + 2 | ||
end | ||
elseif a == "-o" then | ||
if not b then | ||
err = "-o name?" | ||
else | ||
o_name = b | ||
i = i + 2 | ||
end | ||
else | ||
err = "unknown arg: " .. a | ||
end | ||
if err then | ||
-- exit, giving a hint on the way out | ||
error(err) | ||
end | ||
end | ||
return i_name, o_name | ||
end | ||
|
||
-- create or return file handles | ||
local function get_fd(name: string, mode: string, default: FILE): FILE, string | ||
if not name then | ||
return default | ||
end | ||
|
||
local fd, err = io.open(name, mode) | ||
if not fd then | ||
return nil, err | ||
end | ||
|
||
-- main ----------------------------------------------------------------------- | ||
local function main(f: Handles): integer | ||
local lines = f.i:read("a") | ||
-- do work on input, then write it out -- | ||
f.o:write(lines) | ||
return 0 | ||
return fd | ||
end | ||
|
||
-- get handles record | ||
local function get_handles(input_name: string, output_name: string): Handles | ||
local handles: Handles = {} | ||
local err: string | ||
|
||
-- command line --------------------------------------------------------------- | ||
local fin, fout = "", "" -- input and output file names | ||
local errstr = "" | ||
local i = 1 | ||
while i <= #arg do | ||
local a, b = arg[i], arg[i+1] | ||
if a == "-i" then | ||
if not b then | ||
errstr = "-i filename?" | ||
else | ||
fin = b | ||
i = i + 2 | ||
end | ||
elseif a == "-o" then | ||
if not b then | ||
errstr = "-o filename?" | ||
else | ||
fout = b | ||
i = i + 2 | ||
end | ||
else | ||
errstr = "unknown arg: " .. a | ||
end | ||
if errstr ~= "" then -- exit, giving a hint on the way out | ||
error(errstr) | ||
end | ||
handles.input, err = get_fd(input_name, "r", io.stdin) | ||
if err then | ||
error(err) | ||
end | ||
|
||
handles.output, err = get_fd(output_name, "w", io.stdout) | ||
if err then | ||
error(err) | ||
end | ||
|
||
return handles | ||
end | ||
|
||
-- create file handles, as needed | ||
local handle: Handles = {} | ||
if fin == "" then | ||
handle.i = io.stdin | ||
else | ||
handle.i = assert(io.open(fin, "r")) | ||
-- do some work using the file handles | ||
local function process_handles(h: Handles) | ||
local lines = h.input:read("*a") | ||
h.input:close() | ||
|
||
-- simple example of doing work on the input: | ||
-- convert it to ASCII uppercase | ||
lines = lines:upper() | ||
|
||
h.output:write(lines) | ||
h.output:close() | ||
end | ||
if fout == "" then | ||
handle.o = io.stdout | ||
else | ||
handle.o = assert(io.open(fout, "w")) | ||
|
||
local function main(args: {string}): integer | ||
local input_name, output_name = parse_arguments(args) | ||
|
||
local h = get_handles(input_name, output_name) | ||
|
||
process_handles(h) | ||
|
||
os.exit(0) | ||
end | ||
|
||
-- launch the main function | ||
return main(handle) | ||
main(arg) |