├── .gitmodules ├── README ├── erlapp.Makefile ├── erlapp.app.src ├── erlapp.erl ├── erlapp.gitignore ├── erlapp.hrl ├── erlapp.rebar.config ├── erlapp.start.args ├── erlapp.start.sh ├── erlapp.template ├── erlapp_app.erl ├── erlapp_server.erl └── erlapp_sup.erl /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "sync"] 2 | path = erlapp.dev/sync 3 | url = https://github.com/rustyio/sync.git 4 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | 2 | 3 | erlapp.template 4 | 5 | a basic erlang/OTP application skeleton 6 | 7 | This is a minimal erlang/OTP app, with everything you need to get up and 8 | running. It tries to follow best practices, while providing everything necessary 9 | to start development. 10 | Compared to rebar's "create-app", erlapp is much more complete. It includes 11 | the following files and folders: 12 | 13 | ebin/ % .app and .beam files 14 | deps/ % dependencies 15 | dev/ 16 | | start % startup script 17 | | start.args % startup arguments 18 | | 19 | priv/ % application-specific files 20 | src/ 21 | | erlapp.app.src % erlapp.app template 22 | | erlapp.erl % entry-point 23 | | erlapp_app.erl % application 24 | | erlapp_sup.erl % supervisor 25 | | erlapp_server.erl % gen_server 26 | | 27 | Makefile 28 | rebar.config 29 | .gitignore 30 | 31 | erlapp also comes with the sync utility, 32 | which recompiles and reloads changed code. 33 | 34 | install 35 | ------- 36 | 37 | Make sure you have the latest version of rebar installed, then clone this 38 | repo into ~/rebar/templates. 39 | 40 | $ mkdir -p ~/.rebar/templates 41 | $ cd ~/.rebar/templates 42 | $ git clone --recursive git://github.com/cloudhead/erlapp.template.git 43 | 44 | setup 45 | ----- 46 | 47 | Create the app skeleton, set `appid` to the app name 48 | 49 | $ rebar create template=erlapp appid=myapp 50 | 51 | Build the application 52 | 53 | $ make all 54 | 55 | Start the development console 56 | 57 | $ dev/start 58 | 59 | Modules should get recompiled/reloaded when their source is changed. You can also 60 | compile the whole project with `make`. Check the Makefile for additional commands. 61 | 62 | 63 | -------------------------------------------------------------------------------- /erlapp.Makefile: -------------------------------------------------------------------------------- 1 | 2 | REBAR = rebar 3 | APP = {{appid}} 4 | 5 | default: compile 6 | 7 | all: deps compile sync 8 | 9 | compile: 10 | $(REBAR) compile 11 | 12 | deps: 13 | $(REBAR) get-deps 14 | 15 | clean: 16 | $(REBAR) clean 17 | 18 | generate: 19 | $(REBAR) generate 20 | chmod u+x rel/$(APP)/bin/$(APP) 21 | 22 | sync: 23 | cd dev/sync && make && cd - 24 | 25 | distclean: clean 26 | $(REBAR) delete-deps 27 | 28 | console: 29 | rel/$(APP)/bin/$(APP) console -pa ../../ebin 30 | 31 | rebuild: 32 | $(REBAR) clean compile generate 33 | chmod u+x rel/$(APP)/bin/$(APP) 34 | 35 | eunit: 36 | $(REBAR) skip_deps=true eunit 37 | 38 | docs: deps 39 | $(REBAR) skip_deps=true doc 40 | 41 | dialyzer: compile 42 | @dialyzer -Wno_return -c apps/$(APP)/ebin 43 | 44 | .PHONY: deps 45 | 46 | -------------------------------------------------------------------------------- /erlapp.app.src: -------------------------------------------------------------------------------- 1 | {application, {{appid}}, [ 2 | {description, ""}, 3 | {vsn, "1"}, 4 | {registered, []}, 5 | {modules, [ 6 | {{appid}}_app, 7 | {{appid}}_sup, 8 | {{appid}}_server 9 | ]}, 10 | {applications, [ 11 | kernel, 12 | stdlib 13 | ]}, 14 | {mod, { 15 | {{appid}}_app, [] 16 | }}, 17 | {env, []} 18 | ]}. 19 | -------------------------------------------------------------------------------- /erlapp.erl: -------------------------------------------------------------------------------- 1 | %% 2 | %% {{appid}}.erl 3 | %% {{appid}} entry point 4 | %% 5 | -module({{appid}}). 6 | 7 | -export([start/0, start_link/0, stop/0]). 8 | 9 | start_link() -> 10 | {{appid}}_sup:start_link(). 11 | 12 | start() -> 13 | application:start({{appid}}). 14 | 15 | stop() -> 16 | application:stop({{appid}}). 17 | 18 | -------------------------------------------------------------------------------- /erlapp.gitignore: -------------------------------------------------------------------------------- 1 | *.beam 2 | .eunit 3 | deps/* 4 | apps/{{appid}}/ebin 5 | dev/* 6 | rel/{{nodeid}} 7 | 8 | -------------------------------------------------------------------------------- /erlapp.hrl: -------------------------------------------------------------------------------- 1 | -define(PRINT(Var), io:format("~p:~p: ~p = ~p~n", [?MODULE, ?LINE, ??Var, Var])). 2 | -------------------------------------------------------------------------------- /erlapp.rebar.config: -------------------------------------------------------------------------------- 1 | %% Directories 2 | {sub_dirs, ["rel"]}. 3 | {lib_dirs, ["deps"]}. 4 | 5 | {{#lager}} 6 | %% Lager transform 7 | {erl_opts, [{parse_transform, lager_transform}]}. 8 | {{/lager}} 9 | 10 | %% Dependencies 11 | {deps, [ 12 | % {misultin, ".*", {git, "git://github.com/ostinelli/misultin", {branch, "master"}}}, 13 | % {json, ".*", {git, "git://github.com/davisp/eep0018", {branch, "master"}}}, 14 | % {webmachine, ".*", {git, "git://github.com/basho/webmachine", {branch, "master"}}}, 15 | % {riakc, ".*", {git, "git://github.com/basho/riak-erlang-client", {branch, "master"}}} 16 | {{#lager}} 17 | {lager, ".*", {git, "git://github.com/basho/lager", {branch, "master"}}} 18 | {{/lager}} 19 | ]}. 20 | 21 | -------------------------------------------------------------------------------- /erlapp.start.args: -------------------------------------------------------------------------------- 1 | 2 | # Start SASL 3 | -boot start_sasl 4 | 5 | # Start main application 6 | -s {{appid}} 7 | 8 | # Start 'sync' script, for auto-reloading 9 | -s sync 10 | 11 | # Node name 12 | -name {{appid}}@127.0.0.1 13 | 14 | # Cookie name 15 | -setcookie riak 16 | 17 | # Kernel polling 18 | +K true 19 | 20 | # 4 async threads 21 | +A 4 22 | -------------------------------------------------------------------------------- /erlapp.start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo Starting {{appid}} with development console.. 4 | 5 | exec erl -pa $PWD/ebin\ 6 | -pa $PWD/deps/*/ebin\ 7 | -pa $PWD/dev/*/ebin\ 8 | -args_file `dirname $0`/start.args 9 | 10 | -------------------------------------------------------------------------------- /erlapp.template: -------------------------------------------------------------------------------- 1 | {variables, [{lager, false}, {appid, "myapp"}]}. 2 | 3 | {template, "erlapp.app.src", "src/{{appid}}.app.src"}. 4 | {template, "erlapp_app.erl", "src/{{appid}}_app.erl"}. 5 | {template, "erlapp_server.erl", "src/{{appid}}_server.erl"}. 6 | {template, "erlapp_sup.erl", "src/{{appid}}_sup.erl"}. 7 | {template, "erlapp.erl", "src/{{appid}}.erl"}. 8 | {template, "erlapp.hrl", "src/{{appid}}.hrl"}. 9 | {template, "erlapp.rebar.config", "rebar.config"}. 10 | {template, "erlapp.start.args", "dev/start.args"}. 11 | {template, "erlapp.start.sh", "dev/start"}. 12 | {template, "erlapp.Makefile", "Makefile"}. 13 | {template, "erlapp.gitignore", ".gitignore"}. 14 | {template, "README", "README"}. 15 | 16 | {chmod, 8#0744, "dev/start"}. 17 | {copy, "erlapp.dev", "dev"}. 18 | 19 | {dir, "deps"}. 20 | {dir, "src"}. 21 | {dir, "priv"}. 22 | {dir, "ebin"}. 23 | 24 | -------------------------------------------------------------------------------- /erlapp_app.erl: -------------------------------------------------------------------------------- 1 | %% 2 | %% {{appid}}_app.erl 3 | %% {{appid}} application 4 | %% 5 | -module({{appid}}_app). 6 | 7 | -behaviour(application). 8 | 9 | %% Application callbacks 10 | -export([start/2, stop/1]). 11 | 12 | %% ~~~~~~~~~~~~~~~~~~~~~ 13 | %% Application callbacks 14 | %% ~~~~~~~~~~~~~~~~~~~~~ 15 | 16 | start(_StartType, _StartArgs) -> 17 | {{#lager}}lager:start(),{{/lager}} 18 | {{appid}}_sup:start_link(). 19 | 20 | stop(_State) -> 21 | ok. 22 | 23 | -------------------------------------------------------------------------------- /erlapp_server.erl: -------------------------------------------------------------------------------- 1 | %% 2 | %% {{appid}}_server.erl 3 | %% {{appid}} server 4 | %% 5 | -module({{appid}}_server). 6 | -behaviour(gen_server). 7 | -define(SERVER, ?MODULE). 8 | 9 | %% ~~~~~~~~~~~~~~~~~~~~ 10 | %% API Function Exports 11 | %% ~~~~~~~~~~~~~~~~~~~~ 12 | 13 | -export([start_link/0]). 14 | 15 | %% ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 16 | %% gen_server Function Exports 17 | %% ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 18 | 19 | -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). 20 | 21 | %% ~~~~~~~~~~~~~~~~~~~~~~~~ 22 | %% API Function Definitions 23 | %% ~~~~~~~~~~~~~~~~~~~~~~~~ 24 | 25 | start_link() -> 26 | gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). 27 | 28 | %% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 29 | %% gen_server Function Definitions 30 | %% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 31 | 32 | init(Args) -> 33 | {ok, Args}. 34 | 35 | handle_call(_Request, _From, State) -> 36 | {noreply, ok, State}. 37 | 38 | handle_cast(_Msg, State) -> 39 | {noreply, State}. 40 | 41 | handle_info(_Info, State) -> 42 | {noreply, State}. 43 | 44 | terminate(_Reason, _State) -> 45 | ok. 46 | 47 | code_change(_OldVsn, State, _Extra) -> 48 | {ok, State}. 49 | 50 | %% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 51 | %% Internal Function Definitions 52 | %% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 53 | 54 | -------------------------------------------------------------------------------- /erlapp_sup.erl: -------------------------------------------------------------------------------- 1 | %% 2 | %% {{appid}}_sup.erl 3 | %% {{appid}} supervisor 4 | %% 5 | -module({{appid}}_sup). 6 | 7 | -behaviour(supervisor). 8 | 9 | %% API 10 | -export([start_link/0]). 11 | 12 | %% Supervisor callbacks 13 | -export([init/1]). 14 | 15 | %% Helper macro for declaring children of supervisor 16 | -define(CHILD(I, Type), {I, {I, start_link, []}, permanent, 5000, Type, [I]}). 17 | 18 | %% ~~~~~~~~~~~~~ 19 | %% API functions 20 | %% ~~~~~~~~~~~~~ 21 | 22 | start_link() -> 23 | supervisor:start_link({local, ?MODULE}, ?MODULE, []). 24 | 25 | %% ~~~~~~~~~~~~~~~~~~~~ 26 | %% Supervisor callbacks 27 | %% ~~~~~~~~~~~~~~~~~~~~ 28 | 29 | init([]) -> 30 | Server = ?CHILD({{appid}}_server, worker), 31 | {ok, { {one_for_one, 5, 10}, [Server]} }. 32 | 33 | --------------------------------------------------------------------------------