aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bitbucket@bruce-hill.com>2018-06-23 18:04:11 -0700
committerBruce Hill <bitbucket@bruce-hill.com>2018-06-23 18:04:23 -0700
commit9f08215dfb179c3c37c18016fb0eafb7ec6e681e (patch)
tree6d1108b07b9a0a57dbc6c3701bf9971c9144da40
parent247e55059ce94521895f362f5cdfdebf49bfb8e1 (diff)
Moved console colors from core/ into lib/
-rw-r--r--core/metaprogramming.nom2
-rw-r--r--core/text.nom18
-rw-r--r--lib/consolecolor.nom19
-rw-r--r--lib/version.nom2
-rwxr-xr-xnomsu326
-rw-r--r--nomsu.lua5
-rwxr-xr-xnomsu.moon4
-rw-r--r--tests/colors.nom2
-rw-r--r--tests/text.nom1
-rw-r--r--utils.lua10
10 files changed, 348 insertions, 41 deletions
diff --git a/core/metaprogramming.nom b/core/metaprogramming.nom
index 8b33e52..f9cb4e9 100644
--- a/core/metaprogramming.nom
+++ b/core/metaprogramming.nom
@@ -2,7 +2,7 @@
This File contains actions for making actions and compile-time actions and some helper
functions to make that easier.
-lua> "NOMSU_CORE_VERSION = 1"
+lua> "NOMSU_CORE_VERSION = 2"
lua> ".."
nomsu.COMPILE_ACTIONS["% -> %"] = function(nomsu, tree, \%args, \%body)
diff --git a/core/text.nom b/core/text.nom
index b576127..a9b2540 100644
--- a/core/text.nom
+++ b/core/text.nom
@@ -37,23 +37,5 @@ lua> ".."
local lua = "'"..e.."'"
nomsu.COMPILE_ACTIONS[name] = (function(nomsu, tree) return LuaCode.Value(tree.source, lua) end)
end
- local colors = {
- ["reset color"]="\\\\27[0m", bright="\\\\27[1m", dim="\\\\27[2m", underscore="\\\\27[4m",
- blink="\\\\27[5m", inverse="\\\\27[7m", hidden="\\\\27[8m",
-
- black="\\\\27[30m", red="\\\\27[31m", green="\\\\27[32m", yellow="\\\\27[33m", blue="\\\\27[34m",
- magenta="\\\\27[35m", cyan="\\\\27[36m", white="\\\\27[37m",
-
- ["on black"]="\\\\27[40m", ["on red"]="\\\\27[41m", ["on green"]="\\\\27[42m", ["on yellow"]="\\\\27[43m",
- ["on blue"]="\\\\27[44m", ["on magenta"]="\\\\27[45m", ["on cyan"]="\\\\27[46m", ["on white"]="\\\\27[47m",
- };
- for name, c in pairs(colors) do
- local color = "'"..c.."'";
- local reset = "'"..colors["reset color"].."'";
- nomsu.COMPILE_ACTIONS[name] = (function(nomsu, tree) return LuaCode.Value(tree.source, color) end)
- nomsu.COMPILE_ACTIONS[name.." %"] = (function(nomsu, tree, text)
- return LuaCode.Value(tree.source, color, "..", nomsu:tree_to_lua(text), "..", reset);
- end)
- end
end
diff --git a/lib/consolecolor.nom b/lib/consolecolor.nom
new file mode 100644
index 0000000..3a53849
--- /dev/null
+++ b/lib/consolecolor.nom
@@ -0,0 +1,19 @@
+use "core"
+
+%colors <- {..}
+ normal:0, "reset color":0, bright:1, bold:1, dim:2, italic:3, underscore:4
+ "slow blink":5, "fast blink": 6, reverse:7, inverse:7, inverted:7, hidden:8
+ # There's some other codes, but they're not currently implemented
+ black:30, red:31, green:32, yellow:33, blue:34, magenta:35, cyan:36, white:37
+ "on black":40, "on red":41, "on green":42, "on yellow":43, "on blue":44
+ "on magenta":45, "on cyan":46, "on white":47
+
+for %name = %colornum in %colors
+ with {%escapecode: "\27[\(%colornum)m"}
+ lua> ".."
+ nomsu.COMPILE_ACTIONS[\%name] = function(nomsu, tree)
+ return LuaCode.Value(tree.source, repr(\%escapecode))
+ end
+ nomsu.COMPILE_ACTIONS[\%name.." %"] = function(nomsu, tree, text)
+ return LuaCode.Value(tree.source, repr(\%escapecode), "..", nomsu:compile(text), "..'\\\\27[0m'")
+ end
diff --git a/lib/version.nom b/lib/version.nom
index 3b90888..3e9a29d 100644
--- a/lib/version.nom
+++ b/lib/version.nom
@@ -1 +1 @@
-lua> "NOMSU_LIB_VERSION = 2"
+lua> "NOMSU_LIB_VERSION = 3"
diff --git a/nomsu b/nomsu
index af9993d..01127e7 100755
--- a/nomsu
+++ b/nomsu
@@ -1,20 +1,312 @@
-#!/bin/bash
-while getopts ':V:' flag; do
- case "${flag}" in
- V) VERSION="${OPTARG/./\.}\\b" ;;
- esac
-done
+#!/usr/local/bin/lua
+local NOMSU_VERSION, NOMSU_LIB, NOMSU_SHARE = [[]], [[/usr/local/lib/nomsu]], [[/usr/local/share/nomsu]]
+if NOMSU_VERSION and NOMSU_LIB and NOMSU_SHARE then
+ local ver_bits
+ do
+ local _accum_0 = { }
+ local _len_0 = 1
+ for ver_bit in NOMSU_VERSION:gmatch("[0-9]+") do
+ _accum_0[_len_0] = ver_bit
+ _len_0 = _len_0 + 1
+ end
+ ver_bits = _accum_0
+ end
+ local partial_vers
+ do
+ local _accum_0 = { }
+ local _len_0 = 1
+ for i = #ver_bits, 1, -1 do
+ _accum_0[_len_0] = table.concat(ver_bits, '.', 1, i)
+ _len_0 = _len_0 + 1
+ end
+ partial_vers = _accum_0
+ end
+ package.path = table.concat((function()
+ local _accum_0 = { }
+ local _len_0 = 1
+ for _index_0 = 1, #partial_vers do
+ local v = partial_vers[_index_0]
+ _accum_0[_len_0] = tostring(NOMSU_SHARE) .. "/" .. tostring(v) .. "/?.lua"
+ _len_0 = _len_0 + 1
+ end
+ return _accum_0
+ end)(), ";") .. ";" .. package.path
+ package.cpath = table.concat((function()
+ local _accum_0 = { }
+ local _len_0 = 1
+ for _index_0 = 1, #partial_vers do
+ local v = partial_vers[_index_0]
+ _accum_0[_len_0] = tostring(NOMSU_LIB) .. "/" .. tostring(v) .. "/?.so"
+ _len_0 = _len_0 + 1
+ end
+ return _accum_0
+ end)(), ";") .. ";" .. package.cpath
+ package.nomsupath = table.concat((function()
+ local _accum_0 = { }
+ local _len_0 = 1
+ for _index_0 = 1, #partial_vers do
+ local v = partial_vers[_index_0]
+ _accum_0[_len_0] = tostring(NOMSU_SHARE) .. "/" .. tostring(v)
+ _len_0 = _len_0 + 1
+ end
+ return _accum_0
+ end)(), ";")
+end
+local EXIT_SUCCESS, EXIT_FAILURE = 0, 1
+local usage = [=[Nomsu Compiler
-if [[ $VERSION ]]; then
- candidates=$(ls $(dirname $BASH_SOURCE) | grep "^nomsu$VERSION[0-9.]*$")
-else
- candidates=$(ls $(dirname $BASH_SOURCE) | grep "^nomsu[0-9.]\+$")
-fi
+Usage: (lua nomsu.lua | moon nomsu.moon) [-V version] [-i] [-O] [-v] [-c] [-f] [-s] [--help] [--version] [-p print_file] file1 file2... [-- nomsu args...]
-if [[ $candidates ]]; then
- eval $(dirname $BASH_SOURCE)/$(echo "$candidates" | sort -V | tail -n 1) $@
+OPTIONS
+ -i Run the compiler in interactive mode (REPL)
+ -O Run the compiler in optimized mode (use precompiled .lua versions of Nomsu files, when available)
+ -v Verbose: print compiled lua code
+ -c Compile .nom files into .lua files
+ -f Auto-format the given Nomsu file and print the result.
+ -s Check the program for syntax errors.
+ -h/--help Print this message.
+ --version Print the version number and exit.
+ -V specify which Nomsu version is desired
+ -p <file> Print to the specified file instead of stdout.
+ <input> Input file can be "-" to use stdin.
+]=]
+local ok, _ = pcall(function()
+ lpeg = require('lpeg')
+ re = require('re')
+end)
+if not ok then
+ print("Error: unable to find the 'lpeg' Lua module. Please install LPEG either from http://www.inf.puc-rio.br/~roberto/lpeg/re.html or, if you use luarocks: `luarocks install lpeg`")
+ os.exit(EXIT_FAILURE)
+end
+local Errhand = require("error_handling")
+local NomsuCompiler = require("nomsu_compiler")
+local NomsuCode, LuaCode, Source
+do
+ local _obj_0 = require("code_obj")
+ NomsuCode, LuaCode, Source = _obj_0.NomsuCode, _obj_0.LuaCode, _obj_0.Source
+end
+local repr
+repr = require("utils").repr
+local STDIN, STDOUT, STDERR = "/dev/fd/0", "/dev/fd/1", "/dev/fd/2"
+if not arg or debug.getinfo(2).func == require then
+ return NomsuCompiler
+end
+local parser = re.compile([[ args <- {| (flag ";")* {:inputs: {| ({file} ";")* |} :} {:nomsu_args: {| ("--;" ({[^;]*} ";")*)? |} :} ";"? |} !.
+ flag <-
+ {:interactive: ("-i" -> true) :}
+ / {:optimized: ("-O" -> true) :}
+ / {:format: ("-f" -> true) :}
+ / {:syntax: ("-s" -> true) :}
+ / {:print_file: "-p" ";" {file} :}
+ / {:compile: ("-c" -> true) :}
+ / {:verbose: ("-v" -> true) :}
+ / {:help: (("-h" / "--help") -> true) :}
+ / {:version: ("--version" -> true) :}
+ / {:requested_version: "-V" ((";")? {([0-9.])+})? :}
+ file <- "-" / [^;]+
+]], {
+ ["true"] = function()
+ return true
+ end
+})
+local arg_string = table.concat(arg, ";") .. ";"
+local args = parser:match(arg_string)
+if not args or args.help then
+ print(usage)
+ os.exit(EXIT_FAILURE)
+end
+local files = require("files")
+local nomsu = NomsuCompiler
+nomsu.arg = args.nomsu_args
+if args.version then
+ nomsu:run('use "core"\nsay (Nomsu version)')
+ os.exit(EXIT_SUCCESS)
+end
+FILE_CACHE = setmetatable({ }, {
+ __index = function(self, filename)
+ local file = io.open(filename)
+ if not (file) then
+ return nil
+ end
+ local contents = file:read("*a")
+ file:close()
+ self[filename] = contents
+ return contents
+ end
+})
+local run
+run = function()
+ for i, input in ipairs(args.inputs) do
+ if input == "-" then
+ args.inputs[i] = STDIN
+ end
+ end
+ if #args.inputs == 0 and not args.interactive then
+ args.inputs = {
+ "core"
+ }
+ args.interactive = true
+ end
+ local print_file
+ if args.print_file == "-" then
+ print_file = io.stdout
+ elseif args.print_file then
+ print_file = io.open(args.print_file, 'w')
+ else
+ print_file = io.stdout
+ end
+ if print_file == nil then
+ nomsu.print = function() end
+ elseif print_file ~= io.stdout then
+ nomsu.print = function(...)
+ local N = select("#", ...)
+ if N > 0 then
+ print_file:write(tostring(select(1, ...)))
+ for i = 2, N do
+ print_file:write('\t', tostring(select(1, ...)))
+ end
+ end
+ print_file:write('\n')
+ return print_file:flush()
+ end
+ end
+ local input_files = { }
+ local to_run = { }
+ local _list_0 = args.inputs
+ for _index_0 = 1, #_list_0 do
+ local input = _list_0[_index_0]
+ local found = false
+ for f in files.walk(input) do
+ input_files[#input_files + 1] = f
+ to_run[f] = true
+ found = true
+ end
+ if not found then
+ error("Could not find: " .. tostring(input))
+ end
+ end
+ nomsu.can_optimize = function(f)
+ if not (args.optimized) then
+ return false
+ end
+ if to_run[f] then
+ return false
+ end
+ return true
+ end
+ if args.compile or args.verbose then
+ nomsu.on_compile = function(code, from_file)
+ if not (to_run[from_file]) then
+ return
+ end
+ if args.verbose then
+ io.write(tostring(code), "\n")
+ end
+ if args.compile and from_file:match("%.nom$") then
+ local output_filename = from_file:gsub("%.nom$", ".lua")
+ local output_file = io.open(output_filename, 'w')
+ output_file:write(tostring(code))
+ output_file:flush()
+ print(("Compiled %-25s -> %s"):format(from_file, output_filename))
+ return output_file:close()
+ end
+ end
+ end
+ local parse_errs = { }
+ for _index_0 = 1, #input_files do
+ local filename = input_files[_index_0]
+ if args.syntax then
+ local file_contents = io.open(filename):read('*a')
+ local err
+ ok, err = pcall(nomsu.parse, nomsu, file_contents, Source(filename, 1, #file_contents))
+ if not ok then
+ table.insert(parse_errs, err)
+ elseif print_file then
+ print_file:write("Parse succeeded: " .. tostring(filename) .. "\n")
+ print_file:flush()
+ end
+ elseif args.format then
+ local file = files.read(filename)
+ if not file then
+ error("File does not exist: " .. tostring(filename), 0)
+ end
+ local tree = nomsu:parse(file, Source(filename, 1, #file))
+ local formatted = tostring(nomsu:tree_to_nomsu(tree))
+ if print_file then
+ print_file:write(formatted, "\n")
+ print_file:flush()
+ end
+ elseif filename == STDIN then
+ local file = io.input():read("*a")
+ files.spoof('stdin', file)
+ nomsu:run(file, Source('stdin', 1, #file))
+ else
+ nomsu:run_file(filename)
+ end
+ end
+ if #parse_errs > 0 then
+ io.stderr:write(table.concat(parse_errs, "\n\n"))
+ io.stderr:flush()
+ os.exit(EXIT_FAILURE)
+ elseif args.syntax then
+ os.exit(EXIT_SUCCESS)
+ end
+ if args.interactive then
+ nomsu:run('say "\\n\\(bright)\\(underscore)Welcome to the Nomsu v\\(Nomsu version) interactive console!\\(reset color)\\n press \'enter\' twice to run a command\\n"')
+ local ready_to_quit = false
+ nomsu.A_quit = function()
+ ready_to_quit = true
+ return print("Goodbye!")
+ end
+ nomsu.A_exit = nomsu.A_quit
+ nomsu.A_help = function()
+ print("This is the Nomsu v" .. tostring(nomsu.A_Nomsu_version()) .. " interactive console.")
+ print("You can type in Nomsu code here and hit 'enter' twice to run it.")
+ return print("To exit, type 'exit' or 'quit' and hit enter twice")
+ end
+ for repl_line = 1, math.huge do
+ io.write(colored.bright(colored.yellow(">> ")))
+ local buff = { }
+ while true do
+ io.write(colors.bright)
+ local line = io.read("*L")
+ io.write(colors.reset)
+ if line == "\n" or not line then
+ if #buff > 0 then
+ io.write("\027[1A\027[2K")
+ end
+ break
+ end
+ line = line:gsub("\t", " ")
+ table.insert(buff, line)
+ io.write(colored.dim(colored.yellow(".. ")))
+ end
+ if #buff == 0 then
+ break
+ end
+ buff = table.concat(buff)
+ local pseudo_filename = "user input #" .. repl_line
+ files.spoof(pseudo_filename, buff)
+ local err_hand
+ err_hand = function(error_message)
+ return Errhand.print_error(error_message)
+ end
+ local ret
+ ok, ret = xpcall(nomsu.run, err_hand, nomsu, buff, Source(pseudo_filename, 1, #buff))
+ if ok and ret ~= nil then
+ print("= " .. repr(ret))
+ elseif not ok then
+ Errhand.print_error(ret)
+ end
+ if ready_to_quit then
+ break
+ end
+ end
+ end
+end
+local has_ldt, ldt = pcall(require, 'ldt')
+if has_ldt then
+ return ldt.guard(run)
else
- echo "Failed to find a Nomsu version matching the regex: \"nomsu$VERSION\""
- echo "The versions available are:"
- ls $(dirname $BASH_SOURCE) | grep "^nomsu[0-9.]\+$" | sed 's/^/ * /'
-fi
+ return Errhand.run_safely(run)
+end
diff --git a/nomsu.lua b/nomsu.lua
index cfa515a..bb044b4 100644
--- a/nomsu.lua
+++ b/nomsu.lua
@@ -173,9 +173,14 @@ run = function()
local _list_0 = args.inputs
for _index_0 = 1, #_list_0 do
local input = _list_0[_index_0]
+ local found = false
for f in files.walk(input) do
input_files[#input_files + 1] = f
to_run[f] = true
+ found = true
+ end
+ if not found then
+ error("Could not find: " .. tostring(input))
end
end
nomsu.can_optimize = function(f)
diff --git a/nomsu.moon b/nomsu.moon
index 19e7b26..da9f9bd 100755
--- a/nomsu.moon
+++ b/nomsu.moon
@@ -112,9 +112,13 @@ run = ->
input_files = {}
to_run = {}
for input in *args.inputs
+ found = false
for f in files.walk(input)
input_files[#input_files+1] = f
to_run[f] = true
+ found = true
+ if not found
+ error("Could not find: #{input}")
nomsu.can_optimize = (f)->
return false unless args.optimized
diff --git a/tests/colors.nom b/tests/colors.nom
new file mode 100644
index 0000000..b3c22e7
--- /dev/null
+++ b/tests/colors.nom
@@ -0,0 +1,2 @@
+use "lib/consolecolor.nom"
+say: bright: green "Color test passed."
diff --git a/tests/text.nom b/tests/text.nom
index 025e793..4b7f952 100644
--- a/tests/text.nom
+++ b/tests/text.nom
@@ -8,7 +8,6 @@ assume ((["x","y"] joined) = "xy") or barf "joined failed"
assume (("asdf" capitalized) = "Asdf") or barf "capitalized failed"
assume (("asdf" with "X" instead of "s") = "aXdf") or barf "substitution failed"
assume ("\n" = (newline)) or barf "Text literals failed."
-%x <- "\(green)hello\(reset color)"
assume (("x" + "y") = "xy")
assume ((lines in "one\ntwo") = ["one", "two"])
diff --git a/utils.lua b/utils.lua
index ac43757..32056e7 100644
--- a/utils.lua
+++ b/utils.lua
@@ -1,5 +1,6 @@
-- A collection of helper utility functions
--
+local match, gmatch, gsub = string.match, string.gmatch, string.gsub
local function is_list(t)
if type(t) ~= 'table' then
return false
@@ -40,7 +41,7 @@ local function repr(x, depth)
if k == i then
ret[#ret+1] = repr(x[i], depth)
i = i + 1
- elseif type(k) == 'string' and k:match("[_a-zA-Z][_a-zA-Z0-9]*") then
+ elseif type(k) == 'string' and match(k,"[_a-zA-Z][_a-zA-Z0-9]*") then
ret[#ret+1] = k.."= "..repr(v,depth)
else
ret[#ret+1] = "["..repr(k,depth).."]= "..repr(v,depth)
@@ -49,7 +50,10 @@ local function repr(x, depth)
return "{"..table.concat(ret, ", ").."}"
end
elseif x_type == 'string' then
- local escaped = x:gsub("\\", "\\\\"):gsub("\n","\\n"):gsub('"', '\\"')
+ local escaped = gsub(x, "\\", "\\\\")
+ escaped = gsub(escaped, "\n", "\\n")
+ escaped = gsub(escaped, '"', '\\"')
+ escaped = gsub(escaped, "[%c%z]", function(c) return "\\"..c:byte() end)
return '"'..escaped..'"'
else
return tostring(x)
@@ -69,7 +73,7 @@ local function split(str, sep)
sep = "%s"
end
local ret = {}
- for chunk in str:gmatch("[^"..sep.."]+") do
+ for chunk in gmatch(str, "[^"..sep.."]+") do
ret[#ret+1] = chunk
end
return ret