Skip to content

Refactor & overhaul moonc and watchers #380

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
LUA ?= lua5.1
LUA_VERSION = $(shell $(LUA) -e 'print(_VERSION:match("%d%.%d"))')
LUAROCKS = luarocks-$(LUA_VERSION)
LUA_PATH_MAKE = $(shell $(LUAROCKS) path --lr-path);./?.lua;./?/init.lua
LUA_CPATH_MAKE = $(shell $(LUAROCKS) path --lr-cpath);./?.so
LUA_PATH_MAKE = $(shell $(LUAROCKS) path --lr-path);./?.lua;./?/init.lua;$(LUA_PATH)
LUA_CPATH_MAKE = $(shell $(LUAROCKS) path --lr-cpath);./?.so;$(LUA_CPATH)

.PHONY: test local compile compile_system watch lint count show

test:
busted
LUA_PATH='$(LUA_PATH_MAKE)' LUA_CPATH='$(LUA_CPATH_MAKE)' busted

show:
# LUA $(LUA)
Expand All @@ -22,7 +22,7 @@ local: compile
compile:
LUA_PATH='$(LUA_PATH_MAKE)' LUA_CPATH='$(LUA_CPATH_MAKE)' $(LUA) bin/moonc moon/ moonscript/
echo "#!/usr/bin/env lua" > bin/moon
$(LUA) bin/moonc -p bin/moon.moon >> bin/moon
LUA_PATH='$(LUA_PATH_MAKE)' LUA_CPATH='$(LUA_CPATH_MAKE)' $(LUA) bin/moonc -p bin/moon.moon >> bin/moon
echo "-- vim: set filetype=lua:" >> bin/moon

compile_system:
Expand Down
232 changes: 2 additions & 230 deletions bin/moonc
Original file line number Diff line number Diff line change
@@ -1,232 +1,4 @@
#!/usr/bin/env lua

local argparse = require "argparse"
local lfs = require "lfs"

local parser = argparse()

parser:flag("-l --lint", "Perform a lint on the file instead of compiling")
parser:flag("-v --version", "Print version")
parser:flag("-w --watch", "Watch file/directory for updates")
parser:option("--transform", "Transform syntax tree with module")
parser:mutex(
parser:option("-t --output-to", "Specify where to place compiled files"),
parser:option("-o", "Write output to file"),
parser:flag("-p", "Write output to standard output"),
parser:flag("-T", "Write parse tree instead of code (to stdout)"),
parser:flag("-b", "Write parse and compile time instead of code(to stdout)"),
parser:flag("-X", "Write line rewrite map instead of code (to stdout)")
)
parser:flag("-",
"Read from standard in, print to standard out (Must be only argument)")

local read_stdin = arg[1] == "--" -- luacheck: ignore 113

if not read_stdin then
parser:argument("file/directory"):args("+")
end

local opts = parser:parse()

if opts.version then
local v = require "moonscript.version"
v.print_version()
os.exit()
end

function log_msg(...)
if not opts.p then
io.stderr:write(table.concat({...}, " ") .. "\n")
end
end

local moonc = require("moonscript.cmd.moonc")
local util = require "moonscript.util"
local normalize_dir = moonc.normalize_dir
local compile_and_write = moonc.compile_and_write
local path_to_target = moonc.path_to_target

local function scan_directory(root, collected)
root = normalize_dir(root)
collected = collected or {}

for fname in lfs.dir(root) do
if not fname:match("^%.") then
local full_path = root..fname

if lfs.attributes(full_path, "mode") == "directory" then
scan_directory(full_path, collected)
elseif fname:match("%.moon$") then
table.insert(collected, full_path)
end
end
end

return collected
end

local function remove_dups(tbl, key_fn)
local hash = {}
local final = {}

for _, v in ipairs(tbl) do
local dup_key = key_fn and key_fn(v) or v
if not hash[dup_key] then
table.insert(final, v)
hash[dup_key] = true
end
end

return final
end

-- creates tuples of input and target
local function get_files(fname, files)
files = files or {}

if lfs.attributes(fname, "mode") == "directory" then
for _, sub_fname in ipairs(scan_directory(fname)) do
table.insert(files, {
sub_fname,
path_to_target(sub_fname, opts.output_to, fname)
})
end
else
table.insert(files, {
fname,
path_to_target(fname, opts.output_to)
})
end

return files
end

if read_stdin then
local parse = require "moonscript.parse"
local compile = require "moonscript.compile"

local text = io.stdin:read("*a")
local tree, err = parse.string(text)

if not tree then error(err) end
local code, err, pos = compile.tree(tree)

if not code then
error(compile.format_error(err, pos, text))
end

print(code)
os.exit()
end

local inputs = opts["file/directory"]

local files = {}
for _, input in ipairs(inputs) do
get_files(input, files)
end

files = remove_dups(files, function(f)
return f[2]
end)

-- returns an iterator that returns files that have been updated
local function create_watcher(files)
local watchers = require("moonscript.cmd.watchers")

if watchers.InotifyWacher:available() then
return watchers.InotifyWacher(files):each_update()
end

return watchers.SleepWatcher(files):each_update()
end

if opts.watch then
-- build function to check for lint or compile in watch
local handle_file
if opts.lint then
local lint = require "moonscript.cmd.lint"
handle_file = lint.lint_file
else
handle_file = compile_and_write
end

local watcher = create_watcher(files)
-- catches interrupt error for ctl-c
local protected = function()
local status, file = true, watcher()
if status then
return file
elseif file ~= "interrupted!" then
error(file)
end
end

for fname in protected do
local target = path_to_target(fname, opts.t)

if opts.o then
target = opts.o
end

local success, err = handle_file(fname, target)
if opts.lint then
if success then
io.stderr:write(success .. "\n\n")
elseif err then
io.stderr:write(fname .. "\n" .. err .. "\n\n")
end
elseif not success then
io.stderr:write(table.concat({
"",
"Error: " .. fname,
err,
"\n",
}, "\n"))
elseif success == "build" then
log_msg("Built", fname, "->", target)
end
end

io.stderr:write("\nQuitting...\n")
elseif opts.lint then
local has_linted_with_error;
local lint = require "moonscript.cmd.lint"
for _, tuple in pairs(files) do
local fname = tuple[1]
local res, err = lint.lint_file(fname)
if res then
has_linted_with_error = true
io.stderr:write(res .. "\n\n")
elseif err then
has_linted_with_error = true
io.stderr:write(fname .. "\n" .. err.. "\n\n")
end
end
if has_linted_with_error then
os.exit(1)
end
else
for _, tuple in ipairs(files) do
local fname, target = util.unpack(tuple)
if opts.o then
target = opts.o
end

local success, err = compile_and_write(fname, target, {
print = opts.p,
fname = fname,
benchmark = opts.b,
show_posmap = opts.X,
show_parse_tree = opts.T,
transform_module = opts.transform
})

if not success then
io.stderr:write(fname .. "\t" .. err .. "\n")
os.exit(1)
end
end
end


local moonc = require "moonscript.cmd.moonc"
moonc.main(arg)
27 changes: 24 additions & 3 deletions docs/command_line.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,17 +116,38 @@ files in the same directories.
$ moonc my_script1.moon my_script2.moon ...
```

You can control where the compiled files are put using the `-t` flag, followed
by a directory.
You can control where the compiled files are put using the `-t`/`--output-to`
flag, followed by a directory.

`moonc` can also take a directory as an argument, and it will recursively scan
for all MoonScript files and compile them.

If you use `-t` and also specify a directory as argument, then similar to
`rsync`, handling of whether or not directory names are included in the output
file paths differs depending on whether or not you specify a trailing `/`.

For example, if you have a folder called `src` containing a file `foo.moon`:

```bash
$ moonc -t out src
```

Produces the file `out/src/foo.lua`. Alternatively:

```bash
$ moonc -t out src/
```

Produces the file `out/foo.lua`. It does not matter whether or not there is a
trailing `/` on the `--output-to` directory, only on each of the input
directories specified.

`moonc` can write to standard out by passing the `-p` flag.

The `-w` flag can be used to enable watch mode. `moonc` will stay running, and
watch for changes to the input files. If any of them change then they will be
compiled automatically.
compiled automatically. Watch mode also works in combination with the `-t`
flag.

A full list of flags can be seen by passing the `-h` or `--help` flag.

Expand Down
1 change: 1 addition & 0 deletions moonscript-dev-1.rockspec
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ build = {
["moonscript.cmd.coverage"] = "moonscript/cmd/coverage.lua",
["moonscript.cmd.lint"] = "moonscript/cmd/lint.lua",
["moonscript.cmd.moonc"] = "moonscript/cmd/moonc.lua",
["moonscript.cmd.path_handling"] = "moonscript/cmd/path_handling.lua",
["moonscript.cmd.watchers"] = "moonscript/cmd/watchers.lua",
["moonscript.compile"] = "moonscript/compile.lua",
["moonscript.compile.statement"] = "moonscript/compile/statement.lua",
Expand Down
69 changes: 0 additions & 69 deletions moonscript/cmd/args.lua

This file was deleted.

Loading