mkerl 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.rdoc +14 -0
- data/Rakefile +52 -0
- data/VERSION +1 -0
- data/bin/mkerl +23 -0
- data/lib/mkerl.rb +82 -0
- data/templates/Emakefile +17 -0
- data/templates/Makefile +76 -0
- data/templates/README.markdown +22 -0
- data/templates/app +12 -0
- data/templates/basic_file.erl +12 -0
- data/templates/basic_test.erl +22 -0
- data/templates/gitignore +19 -0
- data/templates/make_boot.erl +64 -0
- data/templates/reloader.erl +123 -0
- data/templates/start.sh +10 -0
- data/templates/supervisor.erl +54 -0
- data/templates/test_suite.erl +8 -0
- data/templates/the_app.erl +19 -0
- data/test/helper.rb +9 -0
- data/test/test_mkerl.rb +7 -0
- metadata +79 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Ari Lerner
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
= mkerl
|
2
|
+
|
3
|
+
A template to start erlang projects.
|
4
|
+
|
5
|
+
This includes tests, reloader, an application, supervisor and a boot file. It's pretty slick
|
6
|
+
|
7
|
+
== Getting started
|
8
|
+
|
9
|
+
gem install mkerl
|
10
|
+
mkerl name [destination/directory] [version_number]
|
11
|
+
|
12
|
+
== Copyright
|
13
|
+
|
14
|
+
Copyright (c) 2010 Ari Lerner. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "mkerl"
|
8
|
+
gem.summary = %Q{A template to start erlang projects.}
|
9
|
+
gem.description = %Q{This includes tests, reloader, an application, supervisor and a boot file. It's pretty slick}
|
10
|
+
gem.email = "arilerner@mac.com"
|
11
|
+
gem.homepage = "http://github.com/auser/mkerl"
|
12
|
+
gem.authors = ["Ari Lerner"]
|
13
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
14
|
+
end
|
15
|
+
Jeweler::GemcutterTasks.new
|
16
|
+
rescue LoadError
|
17
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
18
|
+
end
|
19
|
+
|
20
|
+
require 'rake/testtask'
|
21
|
+
Rake::TestTask.new(:test) do |test|
|
22
|
+
test.libs << 'lib' << 'test'
|
23
|
+
test.pattern = 'test/**/test_*.rb'
|
24
|
+
test.verbose = true
|
25
|
+
end
|
26
|
+
|
27
|
+
begin
|
28
|
+
require 'rcov/rcovtask'
|
29
|
+
Rcov::RcovTask.new do |test|
|
30
|
+
test.libs << 'test'
|
31
|
+
test.pattern = 'test/**/test_*.rb'
|
32
|
+
test.verbose = true
|
33
|
+
end
|
34
|
+
rescue LoadError
|
35
|
+
task :rcov do
|
36
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
task :test => :check_dependencies
|
41
|
+
|
42
|
+
task :default => :test
|
43
|
+
|
44
|
+
require 'rake/rdoctask'
|
45
|
+
Rake::RDocTask.new do |rdoc|
|
46
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
47
|
+
|
48
|
+
rdoc.rdoc_dir = 'rdoc'
|
49
|
+
rdoc.title = "mkerl #{version}"
|
50
|
+
rdoc.rdoc_files.include('README*')
|
51
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
52
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
data/bin/mkerl
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
|
4
|
+
|
5
|
+
require "rubygems"
|
6
|
+
require "mkerl"
|
7
|
+
|
8
|
+
args = ARGV.dup
|
9
|
+
|
10
|
+
def usage
|
11
|
+
puts "Usage: mkerl name [directory] [version]"
|
12
|
+
exit
|
13
|
+
end
|
14
|
+
|
15
|
+
if args.size < 1
|
16
|
+
usage
|
17
|
+
else
|
18
|
+
name = args.shift.strip
|
19
|
+
usage if %w(-h help).include?(name)
|
20
|
+
directory = args.empty? ? File.join(Dir.pwd, name) : args.shift.strip
|
21
|
+
version = args.empty? ? 0.1 : args.shift.strip.to_f
|
22
|
+
Mkerl.new(name, directory, version).run
|
23
|
+
end
|
data/lib/mkerl.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "ERB"
|
3
|
+
class Mkerl
|
4
|
+
attr_reader :name, :root_dir, :version, :created_at
|
5
|
+
# Generate a perfectly clean erlang structure
|
6
|
+
def initialize(name, dir=Dir.pwd, version=0.1)
|
7
|
+
@name = name
|
8
|
+
@root_dir = dir
|
9
|
+
@version = version
|
10
|
+
@created_at = Time.now
|
11
|
+
end
|
12
|
+
|
13
|
+
def run
|
14
|
+
make_dirs
|
15
|
+
add_emakefile
|
16
|
+
add_makefile
|
17
|
+
add_appfile
|
18
|
+
add_gitignore
|
19
|
+
add_basic_files
|
20
|
+
end
|
21
|
+
|
22
|
+
def make_dirs
|
23
|
+
FileUtils.mkdir_p(root_dir)
|
24
|
+
%w(src test include).each do |dir|
|
25
|
+
FileUtils.mkdir_p(File.join(root_dir, dir), :mode => 0755)
|
26
|
+
end
|
27
|
+
# Test dirs
|
28
|
+
%w(src).each do |dir|
|
29
|
+
FileUtils.mkdir_p(File.join(root_dir, "test", dir), :mode => 0755)
|
30
|
+
end
|
31
|
+
%w(ebin deps test/ebin test/fixtures).each do |dir|
|
32
|
+
FileUtils.mkdir_p(File.join(root_dir, dir), :mode => 0755)
|
33
|
+
FileUtils.touch(File.join(root_dir, dir, "empty"))
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def add_emakefile
|
38
|
+
write_template_to("Emakefile")
|
39
|
+
end
|
40
|
+
|
41
|
+
def add_makefile
|
42
|
+
write_template_to("Makefile")
|
43
|
+
end
|
44
|
+
|
45
|
+
def add_appfile
|
46
|
+
write_template_to("app", File.join("ebin", "#{name}.app"))
|
47
|
+
end
|
48
|
+
|
49
|
+
def add_gitignore
|
50
|
+
write_template_to("gitignore", ".gitignore")
|
51
|
+
end
|
52
|
+
|
53
|
+
def add_basic_files
|
54
|
+
write_template_to("basic_file.erl", File.join("src", "#{name}.erl"))
|
55
|
+
write_template_to("start.sh", "start.sh", :chmod => 0755)
|
56
|
+
write_template_to("README.markdown")
|
57
|
+
write_template_to("make_boot.erl", File.join("src", "make_boot.erl"))
|
58
|
+
write_template_to("reloader.erl", File.join("src", "reloader.erl"))
|
59
|
+
write_template_to("supervisor.erl", File.join("src", "#{name}_sup.erl"))
|
60
|
+
write_template_to("the_app.erl", File.join("src", "#{name}_app.erl"))
|
61
|
+
write_template_to("test_suite.erl", File.join("test", "src", "test_suite.erl"))
|
62
|
+
write_template_to("basic_test.erl", File.join("test", "src", "#{name}_test.erl"))
|
63
|
+
end
|
64
|
+
|
65
|
+
# Private stuff
|
66
|
+
private
|
67
|
+
def write_template_to(template_file, dest=nil, opts={})
|
68
|
+
data = template_from_file(template_file)
|
69
|
+
destination = File.join(root_dir, dest.nil? ? template_file : dest)
|
70
|
+
File.open(destination, 'w') {|f| f.write(data) }
|
71
|
+
opts.each do |k,v|
|
72
|
+
if k == :chmod
|
73
|
+
FileUtils.chmod v, destination
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
def template_from_file(file)
|
78
|
+
template = ERB.new open(File.join(File.dirname(__FILE__), "..", "templates", file)).read
|
79
|
+
template.result(binding)
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
data/templates/Emakefile
ADDED
data/templates/Makefile
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
PACKAGE_NAME = <%= name %>
|
2
|
+
PACKAGE_VERSION = 0.1
|
3
|
+
VSN = $(PACKAGE_VERSION)
|
4
|
+
ERLC_FLAGS := -W
|
5
|
+
EBIN_DIR := ./ebin
|
6
|
+
EMULATOR := beam
|
7
|
+
ERL = `which erl`
|
8
|
+
ERLC = `which erlc`
|
9
|
+
DOC_DIR = ../doc
|
10
|
+
SILENCE = @
|
11
|
+
|
12
|
+
ERL_SOURCE_DIRS = \
|
13
|
+
./src
|
14
|
+
|
15
|
+
TEST_DIRS = \
|
16
|
+
./test/src
|
17
|
+
|
18
|
+
#######
|
19
|
+
## DON'T EDIT BELOW HERE, UNLESS YOU REALLY KNOW WHAT YOU ARE DOING
|
20
|
+
#######
|
21
|
+
|
22
|
+
ERL_SOURCES := $(wildcard src/*.erl)
|
23
|
+
TEST_SOURCES := $(wildcard ../etest/test_*.erl)
|
24
|
+
ERLDIR = $(erl -eval 'io:format("~s~n", [code:lib_dir()])' -s init stop -noshell)
|
25
|
+
|
26
|
+
#Helper Functions
|
27
|
+
get_src_from_dir = $(wildcard $1/*.erl)
|
28
|
+
get_src_from_dir_list = $(foreach dir, $1, $(call get_src_from_dir,$(dir)))
|
29
|
+
src_to_beam = $(subst ./src, ./ebin, $(subst .erl,.beam,$1))
|
30
|
+
# src_to_beam = $(subst .erl,.beam,$1)
|
31
|
+
|
32
|
+
SRC = $(call get_src_from_dir_list, $(ERL_SOURCE_DIRS))
|
33
|
+
OBJ = $(call src_to_beam,$(SRC))
|
34
|
+
STUFF_TO_CLEAN += $(OBJ)
|
35
|
+
|
36
|
+
TEST_SRC = $(call get_src_from_dir_list, $(TEST_DIRS))
|
37
|
+
TEST_OBJ = $(call src_to_beam,$(TEST_SRC))
|
38
|
+
STUFF_TO_CLEAN += $(TEST_OBJ)
|
39
|
+
|
40
|
+
DOC_FILES = $(DOC_DIR)/*.html $(DOC_DIR)/*.png $(DOC_DIR)/*.css $(DOC_DIR)/edoc-info
|
41
|
+
|
42
|
+
ALL_OBJ = $(OBJ) $(TEST_OBJ)
|
43
|
+
ALL_SRC = $(SRC) $(TEST_SRC)
|
44
|
+
|
45
|
+
all: $(OBJ)
|
46
|
+
|
47
|
+
docs:
|
48
|
+
$(SILENCE) $(ERL) -noshell -run edoc_run application "'$(PACKAGE_NAME)'" '"."' '[{def,{vsn,"$(VSN)"}}, {dir, "$(DOC_DIR)"}]'
|
49
|
+
|
50
|
+
$(OBJ): $(SRC)
|
51
|
+
$(SILENCE)echo compiling $(notdir $@)
|
52
|
+
$(SILENCE)$(ERLC) $(ERLC_FLAGS) -I./include -o $(EBIN_DIR) $^
|
53
|
+
|
54
|
+
$(TEST_OBJ): $(TEST_SRC)
|
55
|
+
$(SILENCE)echo compiling $(notdir $@)
|
56
|
+
$(SILENCE)$(ERLC) $(ERLC_FLAGS) -I./include -o $(EBIN_DIR) $^
|
57
|
+
|
58
|
+
debug:
|
59
|
+
$(MAKE) DEBUG=-DDEBUG
|
60
|
+
|
61
|
+
test: all $(TEST_OBJ)
|
62
|
+
$(SILENCE) $(ERL) -noshell \
|
63
|
+
-sname local_test \
|
64
|
+
-pa $(EBIN_DIR) \
|
65
|
+
-s test_suite test \
|
66
|
+
-s init stop
|
67
|
+
|
68
|
+
boot: all
|
69
|
+
$(SILENCE) $(ERL) -pa $(EBIN_DIR) -noshell -run make_boot write_scripts $(PACKAGE_NAME) $(VSN)
|
70
|
+
$(SILENCE) mv $(PACKAGE_NAME)-$(VSN).boot $(EBIN_DIR)
|
71
|
+
$(SILENCE) mv $(PACKAGE_NAME)-$(VSN).rel $(EBIN_DIR)
|
72
|
+
$(SILENCE) mv $(PACKAGE_NAME)-$(VSN).script $(EBIN_DIR)
|
73
|
+
|
74
|
+
clean:
|
75
|
+
@(rm -rf $(EBIN_DIR)/*.beam erl_crash.dump $(DOC_FILES))
|
76
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<%= name %>
|
2
|
+
-------------
|
3
|
+
|
4
|
+
### What ###
|
5
|
+
|
6
|
+
What the heck is <%= name %> anyway?
|
7
|
+
|
8
|
+
### Getting started ###
|
9
|
+
|
10
|
+
How to get started
|
11
|
+
|
12
|
+
### Contribute ###
|
13
|
+
|
14
|
+
How to contribute back
|
15
|
+
|
16
|
+
### Plans ###
|
17
|
+
|
18
|
+
Plans for the future
|
19
|
+
|
20
|
+
### Thanks ###
|
21
|
+
|
22
|
+
Ari Lerner
|
data/templates/app
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
-module (<%= name %>_test).
|
2
|
+
-include_lib("eunit/include/eunit.hrl").
|
3
|
+
|
4
|
+
setup() ->
|
5
|
+
ok.
|
6
|
+
|
7
|
+
teardown(_X) ->
|
8
|
+
ok.
|
9
|
+
|
10
|
+
starting_test_() ->
|
11
|
+
{spawn,
|
12
|
+
{setup,
|
13
|
+
fun setup/0,
|
14
|
+
fun teardown/1,
|
15
|
+
[
|
16
|
+
fun sometest/0
|
17
|
+
]
|
18
|
+
}
|
19
|
+
}.
|
20
|
+
|
21
|
+
sometest() ->
|
22
|
+
?assert(false).
|
data/templates/gitignore
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
%%%
|
2
|
+
%%% Make .rel and boot scripts
|
3
|
+
%%%
|
4
|
+
%%% Usage:
|
5
|
+
%%% cd ebin; erl -pa . -noshell -run make_boot write_scripts app version [app version]...
|
6
|
+
%%%
|
7
|
+
%%% e.g.:
|
8
|
+
%%% cd ebin; erl -pa . -noshell -run make_boot write_scripts hermes "0.0.2" stoplight "0.0.1"
|
9
|
+
%%%
|
10
|
+
-module(make_boot).
|
11
|
+
-export([write_scripts/1, write_release_scripts/1]).
|
12
|
+
|
13
|
+
write_scripts(A) ->
|
14
|
+
write_scripts(A, local).
|
15
|
+
|
16
|
+
write_release_scripts(A) ->
|
17
|
+
write_scripts(A, release).
|
18
|
+
|
19
|
+
write_scripts(A, Dest) ->
|
20
|
+
Args = pair_up(A),
|
21
|
+
[Primary|Others] = Args,
|
22
|
+
{Name, Version} = Primary,
|
23
|
+
|
24
|
+
io:format("write_scripts for ~p~n", [Name]),
|
25
|
+
Erts = erlang:system_info(version),
|
26
|
+
application:load(sasl),
|
27
|
+
|
28
|
+
{value, {kernel, _, Kernel}} = lists:keysearch(kernel, 1,
|
29
|
+
application:loaded_applications()),
|
30
|
+
{value, {stdlib, _, Stdlib}} = lists:keysearch(stdlib, 1,
|
31
|
+
application:loaded_applications()),
|
32
|
+
{value, {sasl, _, Sasl}} = lists:keysearch(sasl, 1,
|
33
|
+
application:loaded_applications()),
|
34
|
+
|
35
|
+
Rel = "{release, {\"~s\", \"~s\"}, {erts, \"~s\"}, ["
|
36
|
+
"{kernel, \"~s\"}, {stdlib, \"~s\"}, {sasl, \"~s\"}, {~s, \"~s\"}~s]}.",
|
37
|
+
|
38
|
+
OtherApps = lists:foldl(fun(Elem, AccIn) ->
|
39
|
+
{N1, V1} = Elem,
|
40
|
+
AccIn ++ io_lib:format(", {~p, ~p}", [list_to_atom(N1), V1])
|
41
|
+
end, "", Others),
|
42
|
+
|
43
|
+
Lowername = string:to_lower(Name),
|
44
|
+
LowernameVersion = string:to_lower(Name ++ "-" ++ Version),
|
45
|
+
|
46
|
+
Filename = lists:flatten(LowernameVersion ++ ".rel"),
|
47
|
+
io:format("Writing to ~p (as ~s)~n", [Filename, Lowername]),
|
48
|
+
{ok, Fs} = file:open(Filename, [write]),
|
49
|
+
|
50
|
+
io:format(Fs, Rel, [Name, Version, Erts, Kernel, Stdlib, Sasl, Lowername, Version, OtherApps]),
|
51
|
+
file:close(Fs),
|
52
|
+
|
53
|
+
case Dest of
|
54
|
+
local -> systools:make_script(LowernameVersion, [local]);
|
55
|
+
release ->
|
56
|
+
systools:make_script(LowernameVersion, [{path, ["deps/*/ebin"]}]),
|
57
|
+
systools:make_tar(LowernameVersion)
|
58
|
+
end,
|
59
|
+
halt().
|
60
|
+
|
61
|
+
pair_up([A, B | Tail]) ->
|
62
|
+
[{A,B} | pair_up(Tail)];
|
63
|
+
pair_up([]) ->
|
64
|
+
[].
|
@@ -0,0 +1,123 @@
|
|
1
|
+
%% @copyright 2007 Mochi Media, Inc.
|
2
|
+
%% @author Matthew Dempsky <matthew@mochimedia.com>
|
3
|
+
%%
|
4
|
+
%% @doc Erlang module for automatically reloading modified modules
|
5
|
+
%% during development.
|
6
|
+
|
7
|
+
-module(reloader).
|
8
|
+
-author("Matthew Dempsky <matthew@mochimedia.com>").
|
9
|
+
|
10
|
+
-include_lib("kernel/include/file.hrl").
|
11
|
+
|
12
|
+
-behaviour(gen_server).
|
13
|
+
-export([start/0, start_link/0]).
|
14
|
+
-export([stop/0]).
|
15
|
+
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
|
16
|
+
|
17
|
+
-record(state, {last, tref}).
|
18
|
+
|
19
|
+
%% External API
|
20
|
+
|
21
|
+
%% @spec start() -> ServerRet
|
22
|
+
%% @doc Start the reloader.
|
23
|
+
start() ->
|
24
|
+
gen_server:start({local, ?MODULE}, ?MODULE, [], []).
|
25
|
+
|
26
|
+
%% @spec start_link() -> ServerRet
|
27
|
+
%% @doc Start the reloader.
|
28
|
+
start_link() ->
|
29
|
+
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
|
30
|
+
|
31
|
+
%% @spec stop() -> ok
|
32
|
+
%% @doc Stop the reloader.
|
33
|
+
stop() ->
|
34
|
+
gen_server:call(?MODULE, stop).
|
35
|
+
|
36
|
+
%% gen_server callbacks
|
37
|
+
|
38
|
+
%% @spec init([]) -> {ok, State}
|
39
|
+
%% @doc gen_server init, opens the server in an initial state.
|
40
|
+
init([]) ->
|
41
|
+
{ok, TRef} = timer:send_interval(timer:seconds(1), doit),
|
42
|
+
{ok, #state{last = stamp(), tref = TRef}}.
|
43
|
+
|
44
|
+
%% @spec handle_call(Args, From, State) -> tuple()
|
45
|
+
%% @doc gen_server callback.
|
46
|
+
handle_call(stop, _From, State) ->
|
47
|
+
{stop, shutdown, stopped, State};
|
48
|
+
handle_call(_Req, _From, State) ->
|
49
|
+
{reply, {error, badrequest}, State}.
|
50
|
+
|
51
|
+
%% @spec handle_cast(Cast, State) -> tuple()
|
52
|
+
%% @doc gen_server callback.
|
53
|
+
handle_cast(_Req, State) ->
|
54
|
+
{noreply, State}.
|
55
|
+
|
56
|
+
%% @spec handle_info(Info, State) -> tuple()
|
57
|
+
%% @doc gen_server callback.
|
58
|
+
handle_info(doit, State) ->
|
59
|
+
Now = stamp(),
|
60
|
+
doit(State#state.last, Now),
|
61
|
+
{noreply, State#state{last = Now}};
|
62
|
+
handle_info(_Info, State) ->
|
63
|
+
{noreply, State}.
|
64
|
+
|
65
|
+
%% @spec terminate(Reason, State) -> ok
|
66
|
+
%% @doc gen_server termination callback.
|
67
|
+
terminate(_Reason, State) ->
|
68
|
+
{ok, cancel} = timer:cancel(State#state.tref),
|
69
|
+
ok.
|
70
|
+
|
71
|
+
|
72
|
+
%% @spec code_change(_OldVsn, State, _Extra) -> State
|
73
|
+
%% @doc gen_server code_change callback (trivial).
|
74
|
+
code_change(_Vsn, State, _Extra) ->
|
75
|
+
{ok, State}.
|
76
|
+
|
77
|
+
%% Internal API
|
78
|
+
|
79
|
+
doit(From, To) ->
|
80
|
+
[case file:read_file_info(Filename) of
|
81
|
+
{ok, #file_info{mtime = Mtime}} when Mtime >= From, Mtime < To ->
|
82
|
+
reload(Module);
|
83
|
+
{ok, _} ->
|
84
|
+
unmodified;
|
85
|
+
{error, enoent} ->
|
86
|
+
%% The Erlang compiler deletes existing .beam files if
|
87
|
+
%% recompiling fails. Maybe it's worth spitting out a
|
88
|
+
%% warning here, but I'd want to limit it to just once.
|
89
|
+
gone;
|
90
|
+
{error, Reason} ->
|
91
|
+
io:format("Error reading ~s's file info: ~p~n",
|
92
|
+
[Filename, Reason]),
|
93
|
+
error
|
94
|
+
end || {Module, Filename} <- code:all_loaded(), is_list(Filename)].
|
95
|
+
|
96
|
+
reload(Module) ->
|
97
|
+
io:format("Reloading ~p ...", [Module]),
|
98
|
+
code:purge(Module),
|
99
|
+
case code:load_file(Module) of
|
100
|
+
{module, Module} ->
|
101
|
+
io:format(" ok.~n"),
|
102
|
+
case erlang:function_exported(Module, test, 0) of
|
103
|
+
true ->
|
104
|
+
io:format(" - Calling ~p:test() ...", [Module]),
|
105
|
+
case catch Module:test() of
|
106
|
+
ok ->
|
107
|
+
io:format(" ok.~n"),
|
108
|
+
reload;
|
109
|
+
Reason ->
|
110
|
+
io:format(" fail: ~p.~n", [Reason]),
|
111
|
+
reload_but_test_failed
|
112
|
+
end;
|
113
|
+
false ->
|
114
|
+
reload
|
115
|
+
end;
|
116
|
+
{error, Reason} ->
|
117
|
+
io:format(" fail: ~p.~n", [Reason]),
|
118
|
+
error
|
119
|
+
end.
|
120
|
+
|
121
|
+
|
122
|
+
stamp() ->
|
123
|
+
erlang:localtime().
|
data/templates/start.sh
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
%%%-------------------------------------------------------------------
|
2
|
+
%%% File : <%= name %>_sup.erl
|
3
|
+
%%% Author : Your name
|
4
|
+
%%% Description :
|
5
|
+
%%%
|
6
|
+
%%% Created : <%= created_at %>
|
7
|
+
%%%-------------------------------------------------------------------
|
8
|
+
|
9
|
+
-module(<%= name %>_sup).
|
10
|
+
-behaviour(supervisor).
|
11
|
+
|
12
|
+
%% API
|
13
|
+
-export([
|
14
|
+
start_link/0,
|
15
|
+
start_link/1
|
16
|
+
]).
|
17
|
+
|
18
|
+
%% Supervisor callbacks
|
19
|
+
-export([init/1]).
|
20
|
+
|
21
|
+
-define(SERVER, ?MODULE).
|
22
|
+
|
23
|
+
%%====================================================================
|
24
|
+
%% API functions
|
25
|
+
%%====================================================================
|
26
|
+
%%--------------------------------------------------------------------
|
27
|
+
%% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
|
28
|
+
%% Description: Starts the supervisor
|
29
|
+
%%--------------------------------------------------------------------
|
30
|
+
start_link() ->
|
31
|
+
supervisor:start_link({local, ?SERVER}, ?MODULE, []).
|
32
|
+
|
33
|
+
start_link(Opts) ->
|
34
|
+
supervisor:start_link({local, ?SERVER}, ?MODULE, [Opts]).
|
35
|
+
|
36
|
+
%%====================================================================
|
37
|
+
%% Supervisor callbacks
|
38
|
+
%%====================================================================
|
39
|
+
%%--------------------------------------------------------------------
|
40
|
+
%% Func: init(Args) -> {ok, {SupFlags, [ChildSpec]}} |
|
41
|
+
%% ignore |
|
42
|
+
%% {error, Reason}
|
43
|
+
%% Description: Whenever a supervisor is started using
|
44
|
+
%% supervisor:start_link/[2,3], this function is called by the new process
|
45
|
+
%% to find out about restart strategy, maximum restart frequency and child
|
46
|
+
%% specifications.
|
47
|
+
%%--------------------------------------------------------------------
|
48
|
+
init([Opts]) ->
|
49
|
+
AppSrv = {the_<%= name %>,{<%= name %>, start_link, [Opts]}, permanent,2000,worker,dynamic},
|
50
|
+
{ok,{{one_for_one,5,10}, [AppSrv]}}.
|
51
|
+
|
52
|
+
%%====================================================================
|
53
|
+
%% Internal functions
|
54
|
+
%%====================================================================
|
@@ -0,0 +1,19 @@
|
|
1
|
+
%%%-------------------------------------------------------------------
|
2
|
+
%%% File : <%= name %>_app.erl
|
3
|
+
%%% Author : Your name
|
4
|
+
%%% Description :
|
5
|
+
%%%
|
6
|
+
%%% Created : <%= created_at %>
|
7
|
+
%%%-------------------------------------------------------------------
|
8
|
+
|
9
|
+
-module (<%= name %>_app).
|
10
|
+
-behaviour(application).
|
11
|
+
|
12
|
+
-export([start/2, stop/1]).
|
13
|
+
|
14
|
+
start(_Type, Args) ->
|
15
|
+
<%= name %>_sup:start_link(Args).
|
16
|
+
|
17
|
+
stop(_State) ->
|
18
|
+
io:format("Stopping <%= name %>...~n"),
|
19
|
+
ok.
|
data/test/helper.rb
ADDED
data/test/test_mkerl.rb
ADDED
metadata
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mkerl
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ari Lerner
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-04-28 00:00:00 -07:00
|
13
|
+
default_executable: mkerl
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: This includes tests, reloader, an application, supervisor and a boot file. It's pretty slick
|
17
|
+
email: arilerner@mac.com
|
18
|
+
executables:
|
19
|
+
- mkerl
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- LICENSE
|
24
|
+
- README.rdoc
|
25
|
+
files:
|
26
|
+
- .document
|
27
|
+
- .gitignore
|
28
|
+
- LICENSE
|
29
|
+
- README.rdoc
|
30
|
+
- Rakefile
|
31
|
+
- VERSION
|
32
|
+
- bin/mkerl
|
33
|
+
- lib/mkerl.rb
|
34
|
+
- templates/Emakefile
|
35
|
+
- templates/Makefile
|
36
|
+
- templates/README.markdown
|
37
|
+
- templates/app
|
38
|
+
- templates/basic_file.erl
|
39
|
+
- templates/basic_test.erl
|
40
|
+
- templates/gitignore
|
41
|
+
- templates/make_boot.erl
|
42
|
+
- templates/reloader.erl
|
43
|
+
- templates/start.sh
|
44
|
+
- templates/supervisor.erl
|
45
|
+
- templates/test_suite.erl
|
46
|
+
- templates/the_app.erl
|
47
|
+
- test/helper.rb
|
48
|
+
- test/test_mkerl.rb
|
49
|
+
has_rdoc: true
|
50
|
+
homepage: http://github.com/auser/mkerl
|
51
|
+
licenses: []
|
52
|
+
|
53
|
+
post_install_message:
|
54
|
+
rdoc_options:
|
55
|
+
- --charset=UTF-8
|
56
|
+
require_paths:
|
57
|
+
- lib
|
58
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: "0"
|
63
|
+
version:
|
64
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: "0"
|
69
|
+
version:
|
70
|
+
requirements: []
|
71
|
+
|
72
|
+
rubyforge_project:
|
73
|
+
rubygems_version: 1.3.5
|
74
|
+
signing_key:
|
75
|
+
specification_version: 3
|
76
|
+
summary: A template to start erlang projects.
|
77
|
+
test_files:
|
78
|
+
- test/helper.rb
|
79
|
+
- test/test_mkerl.rb
|