First commit

This commit is contained in:
rxi
2014-03-05 20:52:47 +00:00
commit fa8d0a3e97
4 changed files with 178 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
lume.lua
__*
*.tmp
*.swp

20
LICENSE Normal file
View File

@@ -0,0 +1,20 @@
Copyright (c) 2014, rxi
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

54
README.md Normal file
View File

@@ -0,0 +1,54 @@
# lurker
Automatically hotswaps changed Lua files into a running
[LÖVE](http://love2d.org) project.
## Installation
Drop the [lurker.lua](lurker.lua?raw=1) and
[lume.lua](https://raw.github.com/rxi/lume/master/lume.lua) files into an
existing project and add the following line inside the `love.update()`
function:
```lua
require("lurker").update()
```
lurker will automatically detect changed files and hotswap them into the
running project.
## Additional Functionality
To more easily make use of additional functionality, the lurker module can be
set to a variable when it is required into the project:
```lua
lurker = require "lurker"
```
### lurker.scan()
As opposed to using the `lurker.update()` function -- such to avoid the
overhead of repeatedly polling for file changes -- you can instead opt to
trigger a scan of the directory by calling `lurker.scan()` manually. If the
scan detects any changes a hotswap is performed.
### lurker.preswap
`lurker.preswap` can be set to a function. This function is called before a
hotswap occurs and is passed the name of the file which will be swapped.
```lua
lurker.preswap = function(f) print("File " .. f .. " swapping...") end
```
### lurker.postswap
`lurker.postswap` can be set to a function. This function is called after a
hotswap occurs and is passed the name of the file which was swapped.
```lua
lurker.postswap = function(f) print("File " .. f .. " was swapped") end
```
### lurker.interval
The interval in seconds for how often the scan of the directory is performed.
This is `.5` by default.
### lurker.path
The directory which is scanned for changes. This is `.` (The project's root) by
default.

100
lurker.lua Normal file
View File

@@ -0,0 +1,100 @@
--
-- lurker
--
-- Copyright (c) 2014, rxi
--
-- This library is free software; you can redistribute it and/or modify it
-- under the terms of the MIT license. See LICENSE for details.
--
local lume = require "lume"
local lurker = { _version = "1.0.0" }
local dir = love.filesystem.enumerate or love.filesystem.getDirectoryItems
local isdir = love.filesystem.isDirectory
local time = love.timer.getTime or os.time
local lastmodified = love.filesystem.getLastModified
function lurker.init()
lurker.print("Initing lurker")
lurker.path = "."
lurker.preswap = function() end
lurker.postswap = function() end
lurker.interval = .5
lurker.last = 0
lurker.files = {}
lume.each(lurker.getchanged(), lurker.resetfile)
return lurker
end
function lurker.print(...)
print("[lurker] " .. lume.format(...))
end
function lurker.listdir(path, recursive, skipdotfiles)
path = (path == ".") and "" or path
local function fullpath(x) return path .. "/" .. x end
local t = {}
for _, f in pairs(lume.map(dir(path), fullpath)) do
if not skipdotfiles or not f:match("/%.[^/]*$") then
if recursive and isdir(f) then
lume.merge(t, lurker.listdir(f, true, true))
else
table.insert(t, lume.trim(f, "/"))
end
end
end
return t
end
function lurker.update()
local diff = time() - lurker.last
if diff > lurker.interval then
lurker.last = lurker.last + diff
lurker.scan()
end
end
function lurker.getchanged()
local function fn(f)
return f:match("%.lua$") and lurker.files[f] ~= lastmodified(f)
end
return lume.filter(lurker.listdir(lurker.path, true, true), fn)
end
function lurker.modname(f)
return (f:gsub("%.lua$", ""):gsub("[/\\]", "."))
end
function lurker.resetfile(f)
lurker.files[f] = lastmodified(f)
end
function lurker.scan()
for _, f in pairs(lurker.getchanged()) do
lurker.print("Hotswapping '{f}'...", {f = f})
lurker.preswap(f)
local modname = lurker.modname(f)
local t, ok, err = lume.time(lume.hotswap, modname)
if ok then
lurker.print("Swapped '{f}' in {t} secs", {f = f, t = t})
else
lurker.print("Failed to swap '{f}' : {e}", {f = f, e = err})
end
lurker.resetfile(f)
lurker.postswap(f)
end
end
return lurker.init()