Pretty up the CLI with ansi escape codes

This commit is contained in:
Starbeamrainbowlabs 2020-09-06 01:47:35 +01:00
parent 28df89ea7f
commit 4928d200d2
Signed by: sbrl
GPG key ID: 1BE5172E637709C2
3 changed files with 135 additions and 24 deletions

View file

@ -59,9 +59,9 @@ To render a 3D maze as a .STL file, do this:
```bash ```bash
# Generate the OpenSCAD file # Generate the OpenSCAD file
lua main.lua maze3d_openscad -w 91 -h 91 -d 71 -f 91x91x71.scad lua main.lua maze3d_openscad -w 15 -h 15 -d 17 -f 15x15x17.scad
# Convert the OpenSCAD file to an STL # Convert the OpenSCAD file to an STL
openscad -o 91x91x71.stl 91x91x71.scad openscad -o 15x15x17.stl 15x15x17.scad
``` ```
![(Horizontal line)](https://starbeamrainbowlabs.com/blog/images/20200831-mazes/hr.png) ![(Horizontal line)](https://starbeamrainbowlabs.com/blog/images/20200831-mazes/hr.png)

View file

@ -1,3 +1,4 @@
local a = require("./utils/ansi")
local strings = require("./utils/strings") local strings = require("./utils/strings")
local debug = require("./utils/print_r") local debug = require("./utils/print_r")
local calculations = require("./utils/calculations") local calculations = require("./utils/calculations")
@ -5,6 +6,12 @@ local maze2d = require("./maze")
local maze3d = require("./maze3d") local maze3d = require("./maze3d")
local openscad = require("./openscad") local openscad = require("./openscad")
-- ANSI escape sequence helpers
function a.header(str) return a.fblue(a.hicol(str)) end
function a.item(str) return a.fyellow(str) end
function a.value(str) return a.fgreen(str) end
local settings = { local settings = {
mode = "help", mode = "help",
extras = {}, extras = {},
@ -65,29 +72,35 @@ end
local function help() local function help()
print([[ print([[
multimaze: Multidimensional maze generator ]]..a.fgreen(a.hicol("multimaze: "))..a.fyellow(a.hicol("Multidimensional maze generator"))..[[
By Starbeamrainbowlabs
Usage: ]]..a.locol("By Starbeamrainbowlabs")..[[
lua main.lua {mode} [{options}]
Modes:
help Displays this message
maze Generates a 2d maze
maze3d Generates a 3d maze
maze3d_openscad Generates a 3d maze as an openscad file
Options: ]]..a.header("Usage:")..[[
-w --width {int} Sets the width of the maze
-h --height {int} Sets the height of the maze lua main.lua ]]..a.item("{mode} [{options}]")..[[
-d --depth {int} Sets the depth of the maze [3d only]
-s --seed {string} Sets the seed
-f --filename {string} Sets the output filename ]]..a.header("Modes:")..[[
--no-invert Don't invert the output [openscad output only]
--scale {int} Sets the scale of the output [openscad output only] ]]..a.item("help")..[[ Displays this message
--path-length {int} Sets the path length ]]..a.item("maze")..[[ Generates a 2d maze
--path-width {int} Sets the path width ]]..a.item("maze3d")..[[ Generates a 3d maze
--path-depth {int} Sets the path depth [3d only] ]]..a.item("maze3d_openscad")..[[ Generates a 3d maze as an openscad file
]]..a.header("Options:")..[[
]]..a.item("-w --width")..a.value(" {int}")..[[ Sets the width of the maze
]]..a.item("-h --height")..a.value(" {int}")..[[ Sets the height of the maze
]]..a.item("-d --depth")..a.value(" {int}")..[[ Sets the depth of the maze [3d only]
]]..a.item("-s --seed")..a.value(" {string}")..[[ Sets the seed
]]..a.item("-f --filename")..a.value(" {string}")..[[ Sets the output filename
]]..a.item("--no-invert")..[[ Don't invert the output [openscad output only]
]]..a.item("--scale")..a.value(" {int}")..[[ Sets the scale of the output [openscad output only]
]]..a.item("--path-length")..a.value(" {int}")..[[ Sets the path length
]]..a.item("--path-width")..a.value(" {int}")..[[ Sets the path width
]]..a.item("--path-depth")..a.value(" {int}")..[[ Sets the path depth [3d only]
]]) ]])
end end
@ -141,7 +154,7 @@ local function maze3d_openscad()
settings.filename, settings.filename,
openscad_settings openscad_settings
) )
print("Maze written to "..settings.filename) print("Maze written to "..a.fgreen(a.hicol(settings.filename)))
end end
local mode_functions = { local mode_functions = {
@ -153,7 +166,8 @@ local mode_functions = {
local selection = mode_functions[settings.mode] local selection = mode_functions[settings.mode]
if not selection then if not selection then
print("Error: Unrecognised mode '"..settings.mode.."'") print(a.fred(a.hicol("Error: Unrecognised mode '"..a.FBLE..settings.mode..a.FRED.."'")))
print()
selection = mode_functions["help"] selection = mode_functions["help"]
end end

97
utils/ansi.lua Normal file
View file

@ -0,0 +1,97 @@
--[[
VT100 ANSI escape sequences.
Ported from the Lantern Build Engine, which si written in Bash.
Other versions:
- Bash, in the Lantern Build Engine: https://gitlab.com/sbrl/lantern-build-engine/-/blob/master/lantern.sh
- Javascript: massCode/Ansi.mjs
- C: massCode/Ansi.cs
Changelog:
6th September 2020:
Initial release - port complete!
]]--
local ansi
if os.getenv("NO_COLOR") ~= nil then
ansi = {
RS = "",
HC = "",
UL = "",
INV = "",
LC = "",
FBLK = "",
FRED = "",
FGRN = "",
FYEL = "",
FBLE = "",
FMAG = "",
FCYN = "",
FWHT = "",
BBLK = "",
BRED = "",
BGRN = "",
BYEL = "",
BBLE = "",
BMAG = "",
BCYN = "",
BWHT = "",
}
else
ansi = {
RS = "\27[0m", -- reset
HC = "\27[1m", -- hicolor
UL = "\27[4m", -- underline
INV = "\27[7m", -- inverse background and foreground
LC = "\27[2m", -- locolor / dim
FBLK = "\27[30m", -- foreground black
FRED = "\27[31m", -- foreground red
FGRN = "\27[32m", -- foreground green
FYEL = "\27[33m", -- foreground yellow
FBLE = "\27[34m", -- foreground blue
FMAG = "\27[35m", -- foreground magenta
FCYN = "\27[36m", -- foreground cyan
FWHT = "\27[37m", -- foreground white
BBLK = "\27[40m", -- background black
BRED = "\27[41m", -- background red
BGRN = "\27[42m", -- background green
BYEL = "\27[43m", -- background yellow
BBLE = "\27[44m", -- background blue
BMAG = "\27[45m", -- background magenta
BCYN = "\27[46m", -- background cyan
BWHT = "\27[47m", -- background white
-- Invalid escape sequence, apparently - we'll need to look into how to do it properly
-- Perhaps knowing the hex code for the character we want would be helpful
-- URL_START = '\e]8;;',
-- URL_DISPLAY_TEXT = '\e\\',
-- URL_END = '\e]8;;\e\\'
}
end
function ansi.wrap(str, start)
return start..str..ansi.RS
end
function ansi.hicol(str) return ansi.wrap(str, ansi.HC) end
function ansi.locol(str) return ansi.wrap(str, ansi.LC) end
function ansi.uline(str) return ansi.wrap(str, ansi.UL) end
function ansi.invert(str) return ansi.wrap(str, ansi.INV) end
function ansi.fblack(str) return ansi.wrap(str, ansi.FBLK) end
function ansi.fred(str) return ansi.wrap(str, ansi.FRED) end
function ansi.fgreen(str) return ansi.wrap(str, ansi.FGRN) end
function ansi.fyellow(str) return ansi.wrap(str, ansi.FYEL) end
function ansi.fblue(str) return ansi.wrap(str, ansi.FBLE) end
function ansi.fmagenta(str) return ansi.wrap(str, ansi.FMAG) end
function ansi.fcyan(str) return ansi.wrap(str, ansi.FCYN) end
function ansi.fwhite(str) return ansi.wrap(str, ansi.FWHT) end
function ansi.bblack(str) return ansi.wrap(str, ansi.FBLK) end
function ansi.bred(str) return ansi.wrap(str, ansi.BRED) end
function ansi.bgreen(str) return ansi.wrap(str, ansi.BGRN) end
function ansi.byellow(str) return ansi.wrap(str, ansi.BYEL) end
function ansi.bblue(str) return ansi.wrap(str, ansi.BBLE) end
function ansi.bmagenta(str) return ansi.wrap(str, ansi.BMAG) end
function ansi.bcyan(str) return ansi.wrap(str, ansi.BCYN) end
function ansi.bwhite(str) return ansi.wrap(str, ansi.BWHT) end
return ansi