Skip to content

Commit

Permalink
Refactor moonc and overhaul watchers
Browse files Browse the repository at this point in the history
- Essentially rewrote both SleepWatcher and InotifyWatcher
- Added test suites for both, including an expanded set of filesystem
  stubs in order to test them in isolation from the underlying
  filesystem
    - The filesystem stubs have their own tests, kek

Improvements as a result of these changes:
- Watch mode will remove "orphaned" .lua output files if/when their
  corresponding .moon input files are deleted
    - But it will not remove .lua files that have no corresponding .moon
      file to begin with, in order to avoid e.g. removing vendored Lua
      modules
- Both Watcher types will properly handle creation of new subdirectories
    - There *shouldn't* be any problematic races with this, although
      inotify's lack of recursive directory watching makes it difficult
      to know for sure
- More of the code is tested, and more of the code now *could* be tested
  (but isn't yet)
- Some bugs were fixed

Downsides:
- Somewhat gnarlier tests
- Moar lines of code
  • Loading branch information
Shados committed Feb 20, 2019
1 parent 5d79bf7 commit 596f6fb
Show file tree
Hide file tree
Showing 10 changed files with 968 additions and 215 deletions.
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
53 changes: 31 additions & 22 deletions moonscript/cmd/moonc.lua
Original file line number Diff line number Diff line change
Expand Up @@ -134,43 +134,52 @@ handle_watch_loop = function(opts, output_to, input_paths, prefix_map)
end
end
end
local watcher = create_watcher(input_paths)
for filename in watcher do
local target = output_for(output_to, prefix_map, filename, "file")
local watcher = create_watcher(output_to, input_paths, prefix_map)
for file_tuple in watcher do
local event_type, filename, target, path_type
event_type, filename, target, path_type = file_tuple[1], file_tuple[2], file_tuple[3], file_tuple[4]
if opts.o then
target = opts.o
end
if opts.lint then
local lint = require("moonscript.cmd.lint")
local success, err = lint.lint_file(filename)
if success then
io.stderr:write(success .. "\n\n")
elseif err then
io.stderr:write(filename .. "\n" .. err .. "\n\n")
if event_type == "changedfile" then
local lint = require("moonscript.cmd.lint")
local success, err = lint.lint_file(filename)
if success then
io.stderr:write(success .. "\n\n")
elseif err then
io.stderr:write(filename .. "\n" .. err .. "\n\n")
end
elseif event_type == "removed" then
remove_orphaned_output(target, path_type)
end
else
local success, err = compile_and_write(filename, target)
if not success then
io.stderr:write(table.concat({
"",
"Error: " .. filename,
err,
"\n"
}, "\n"))
elseif success == "build" then
log_msg("Built", filename, "->", target)
if event_type == "changedfile" then
local success, err = compile_and_write(filename, target)
if not success then
io.stderr:write(table.concat({
"",
"Error: " .. filename,
err,
"\n"
}, "\n"))
elseif success == "build" then
log_msg("Built", filename, "->", target)
end
elseif event_type == "removed" then
remove_orphaned_output(target, path_type)
end
end
end
return io.stderr:write("\nQuitting...\n")
end
create_watcher = function(input_paths)
create_watcher = function(output_to, input_paths, prefix_map)
local watchers = require("moonscript.cmd.watchers")
local watcher
if watchers.InotifyWatcher:available() then
watcher = watchers.InotifyWatcher(input_paths)
watcher = watchers.InotifyWatcher(output_to, input_paths, prefix_map)
else
watcher = watchers.SleepWatcher(input_paths)
watcher = watchers.SleepWatcher(output_to, input_paths, prefix_map)
end
return watcher:each_update()
end
Expand Down
50 changes: 28 additions & 22 deletions moonscript/cmd/moonc.moon
Original file line number Diff line number Diff line change
Expand Up @@ -126,44 +126,50 @@ handle_watch_loop = (opts, output_to, input_paths, prefix_map) ->
else
log_msg "Error removing file", target, err_string

watcher = create_watcher input_paths
watcher = create_watcher output_to, input_paths, prefix_map

for filename in watcher
target = output_for(output_to, prefix_map, filename, "file")
for file_tuple in watcher
{event_type, filename, target, path_type} = file_tuple

if opts.o
target = opts.o

if opts.lint
lint = require "moonscript.cmd.lint"
success, err = lint.lint_file filename
if success
io.stderr\write success .. "\n\n"
elseif err
io.stderr\write filename .. "\n" .. err .. "\n\n"
if event_type == "changedfile"
lint = require "moonscript.cmd.lint"
success, err = lint.lint_file filename
if success
io.stderr\write success .. "\n\n"
elseif err
io.stderr\write filename .. "\n" .. err .. "\n\n"
elseif event_type == "removed"
remove_orphaned_output target, path_type
else
success, err = compile_and_write filename, target
if not success
io.stderr\write table.concat({
"",
"Error: " .. filename,
err,
"\n",
}, "\n")
elseif success == "build"
log_msg "Built", filename, "->", target
if event_type == "changedfile"
success, err = compile_and_write filename, target
if not success
io.stderr\write table.concat({
"",
"Error: " .. filename,
err,
"\n",
}, "\n")
elseif success == "build"
log_msg "Built", filename, "->", target
elseif event_type == "removed"
remove_orphaned_output target, path_type

io.stderr\write "\nQuitting...\n"

create_watcher = (input_paths) ->
create_watcher = (output_to, input_paths, prefix_map) ->
watchers = require "moonscript.cmd.watchers"

-- TODO cli argument to force sleep watcher (as it is potentially a little
-- more reliable)
watcher = if watchers.InotifyWatcher\available!
watchers.InotifyWatcher input_paths
watchers.InotifyWatcher output_to, input_paths, prefix_map
else
watchers.SleepWatcher input_paths
watchers.SleepWatcher output_to, input_paths, prefix_map

return watcher\each_update!

Expand Down
Loading

0 comments on commit 596f6fb

Please sign in to comment.