mkerl 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|