Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

[feature] opa-create: new tool to generate application skeletons

  • Loading branch information...
commit 2b398098595b206a18ce0debc5d547e0e2a7fb37 1 parent 8665198
Cédric Soulas cedricss authored
16 Makefile
View
@@ -63,7 +63,7 @@ opa-packages: $(MYOCAMLBUILD)
.PHONY: stdlib
stdlib: opa-packages
-DISTRIB_TOOLS = opa-bin opa-plugin-builder-bin opa-plugin-browser-bin bslServerLib.ml opa-db-server opa-db-tool opa-cloud opatop opa-translate
+DISTRIB_TOOLS = opa-bin opa-plugin-builder-bin opa-plugin-browser-bin bslServerLib.ml opa-db-server opa-db-tool opa-cloud opatop opa-translate opa-create
.PHONY: distrib
distrib: $(MYOCAMLBUILD)
@@ -74,6 +74,18 @@ distrib: $(MYOCAMLBUILD)
manpages: $(MYOCAMLBUILD)
$(MAKE) -C manpages OCAMLBUILD="$(OCAMLBUILD)" BLDDIR=../$(BUILD_DIR)
+.PHONY: opa-create
+opa-create: $(MYOCAMLBUILD)
+ $(OCAMLBUILD) tools/opa-create/src/opa-create.exe
+ @$(copy-tool-opa-create)
+.PHONY: install-opa-create
+install-opa-create:
+ @$(install-opa-create)
+target-tool-opa-create = tools/opa-create/src/opa-create.exe
+copy-tool-opa-create = mkdir -p $(BUILD_DIR)/bin && $(INSTALL) $(BUILD_DIR)/tools/opa-create/src/opa-create.exe $(BUILD_DIR)/bin/opa-create
+install-opa-create = mkdir -p $(PREFIX)/bin && $(INSTALL) $(BUILD_DIR)/bin/opa-create $(INSTALL_DIR)/bin/opa-create
+
+
##
## INSTALLATION
##
@@ -140,7 +152,7 @@ install-all-plugins: $(addprefix install-plugin-,$(OPA_PLUGINS))
-install-bin:
+install-bin: opa-create
@printf "Installing into $(INSTALL_DIR)/bin\r"
@mkdir -p $(INSTALL_DIR)/bin
@$(if $(wildcard $(BUILD_DIR)/bin/*),$(INSTALL) -r $(BUILD_DIR)/bin/* $(INSTALL_DIR)/bin)
22 build_rules.ml
View
@@ -772,6 +772,7 @@ rule "opa bash_completion: opa-bin -> bash_completion"
(fun env build ->
Seq[Cmd(S[get_tool "opa-bin"; A"--bash-completion"])]);
+
(* -- OPA packages -- *)
let package_to_dir s0 =
@@ -848,7 +849,28 @@ rule "all.plugins"
])
);
+let opa_create_prefix = "tools/opa-create/src/opa-create" in
+let opa_create_src = opa_create_prefix ^ ".opa" in
+let opa_create_dst = opa_create_prefix ^ ".exe" in
+
+let dir_all_files dir =
+ List.filter (fun p -> (not (Pathname.is_directory p))) (dirlist dir)
+in
+
+let dir_rec_all_files dir =
+ let dirs = rec_subdirs [ dir ] in
+ List.fold_right (fun dir acc -> dir_all_files dir @ acc) dirs []
+in
+rule "opa application creator"
+ ~deps:((dir_rec_all_files "tools/opa-create"))
+ ~prods: [opa_create_dst]
+ (fun env build ->
+ Cmd(S[
+ Sh("MLSTATELIBS=\""^ opa_prefix ^"\"");
+ get_tool "opa-bin";
+ A"-o"; P opa_create_dst; P opa_create_src
+ ]));
let package_building ~name ~stamp ~stdlib_only ~rebuild =
rule name
1  build_tools
View
@@ -94,4 +94,3 @@ internal opa-cloud dissemination/spawn.sh
internal gen_opa_manpage opa/gen_opa_manpage.native
internal gen_opatop_manpage opatop/gen_opatop_manpage.native
internal genman.native manpages/genman.native
-
1  tools/_tags
View
@@ -16,3 +16,4 @@
###
# jschecker
<jschecker>: traverse
+<opa-create/**>: traverse
71 tools/opa-create/src/opa-create.opa
View
@@ -0,0 +1,71 @@
+/*
+ Copyright © 2011 MLstate
+
+ This file is part of OPA.
+
+ OPA is free software: you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License, version 3, as published by
+ the Free Software Foundation.
+
+ OPA is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
+ more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with OPA. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * opa-create tool
+ *
+ * @category tools
+ * @author Cedric Soulas
+ * @destination PUBLIC
+ * @stability experimental
+ */
+
+import stdlib.{system, io.file}
+
+SRC_DIR = "tools/opa-create/template/mvc"
+resources = @static_content_directory("tools/opa-create/template/mvc")
+
+function CommandLine_ident(names,description,param_doc)(up) {
+ {CommandLine.default_parser with
+ ~names, ~description, ~param_doc,
+ function on_param(o) { parser { case int=Rule.ident : {no_params:up(int,o)} } }
+ }
+}
+
+list(CommandLine.parser({string name})) cmdline_parsers = [
+ CommandLine_ident(["--name", "-n"],
+ "Application name, without spaces, \"/\" or any other special characters",
+ "app_name (no special characters)")({ function(name, r){ r with ~name}}
+ )
+]
+
+options =
+ cmdline = {
+ init : { name : "wiki" },
+ parsers : cmdline_parsers,
+ anonymous : [],
+ title : "Opa Application Generator"
+ }
+ CommandLine.filter(cmdline)
+
+function write(file, content) {
+ %%BslFile.of_string%%("./{file}", content)
+}
+
+function iter(file, f_content) {
+ n = String.length(SRC_DIR)
+ file = "{options.name}{String.sub(n, String.length(file) - n, file)}"
+ if (File.exists(file)) { warning("File {file} already exists. \nPlease delete it and try again."); System.exit(1) }
+ jlog("Generating {file}")
+ content = String.replace("application_name", options.name, f_content())
+ write(file, content)
+}
+
+StringMap.iter(iter, resources)
+
+jlog("\nNow you can type:\n$ cd {options.name}\n$ make run")
26 tools/opa-create/template/mvc/Makefile
View
@@ -0,0 +1,26 @@
+########################################
+# USER VARIABLES
+
+EXE = application_name.exe
+PACKNAME =
+SRC =
+PCKDIR = ./plugins/
+PCK =
+PLUGIN =
+PLUGINDIR =
+OTHER_DEPENDS = resources/*
+CONF_FILE = configuration
+
+#Compiler variables
+OPACOMPILER ?= opa
+FLAG = --opx-dir _build --import-package stdlib.database.mongo
+PORT = 8080
+
+RUN_OPT = --db-local db/
+
+default: exe
+
+run: exe
+ ./$(EXE) $(RUN_OPT) || true
+
+include Makefile.common
69 tools/opa-create/template/mvc/Makefile.common
View
@@ -0,0 +1,69 @@
+########################################
+# MAKEFILE VARIABLES
+OPACOMPILER ?= opa
+OPA = $(OPACOMPILER) $(FLAG) $(OPAOPT)
+PWD ?= $(shell pwd)
+BUILDDIR ?= $(PWD)/_build
+export BUILDDIR
+OPAGENAPI ?= $(OPACOMPILER) --api-only
+DEPENDS = $(SRC) $(PCK:%=$(BUILDDIR)/%) $(PLUGIN:%=$(BUILDDIR)/%)
+
+ifdef CONF_FILE
+ CONFIG = --conf $(CONF_FILE) --conf-opa-files
+else
+ CONFIG =
+endif
+
+_ = $(shell mkdir -p $(BUILDDIR))
+
+########################################
+# MAIN RULE
+exe : $(EXE)
+pack : $(PACKNAME)
+doc : $(PACKDOC) doc.sub
+
+########################################
+# MAIN PACKAGE BUILDING
+$(PACKNAME) : $(BUILDDIR)/$(PACKNAME)
+
+$(BUILDDIR)/$(PACKNAME) : $(DEPENDS)
+ @echo "### Building package $(PACKNAME)"
+ mkdir -p $(BUILDDIR)
+ $(OPA) --autocompile $(SRC) $(PLUGIN:%=$(BUILDDIR)/%) --build-dir $(BUILDDIR) -I $(BUILDDIR) $(OPAOPT)
+ @rm -rf $(BUILDDIR)/$(PACKNAME)
+ @mv $(PACKNAME) $(BUILDDIR)/
+
+########################################
+# SUBS PACKAGE/PLUGIN BUILDING
+$(BUILDDIR)/%.opx :
+ make $(@:$(BUILDDIR)/%.opx=-C $(PCKDIR)/%) pack
+
+$(BUILDDIR)/%.opp :
+ make $(@:$(BUILDDIR)/%.opp=-C $(PLUGINDIR)/%)
+
+########################################
+# EXECUTABLE BUILDING
+$(EXE) : pack $(SRC) $(MAINSRC) $(DEPENDS) $(OTHER_DEPENDS)
+ @echo "### Building executable $(EXE) "
+ mkdir -p $(BUILDDIR)
+ $(OPA) $(COMPILOPT) $(MAINSRC) $(CONFIG) $(PLUGIN:%=$(BUILDDIR)/%) -o $@ --build-dir $(BUILDDIR)/$(EXE)
+
+$(EXE:%.exe=%.run) : $(EXE)
+ ./$(EXE) -p $(PORT)
+
+########################################
+# Used by recursives makefile
+pack.depends :
+ @echo $(PCK) $(PLUGIN)
+
+########################################
+# CLEANING
+clean ::
+ @$(PCK:%.opx=make -C $(PCKDIR)/% clean &&) $(PLUGIN:%.opp=make -C $(PLUGINDIR)/% clean &&) echo "### Cleaning $(BUILDDIR)";
+ @rm -rf $(BUILDDIR)/* _tracks/*;
+ @if [ -n "$(EXE)" ]; then rm -rf $(EXE); fi
+ @if [ -n "$(PACKDOC)" ]; then rm -rf $(PACKDOC); fi
+
+deep-clean :: clean
+ @rm -rf opa-debug
+
11 tools/opa-create/template/mvc/configuration
View
@@ -0,0 +1,11 @@
+application_name.controller:
+ import application_name.view
+ src/controller.opa
+
+application_name.view:
+ import application_name.model
+ import stdlib.themes.bootstrap
+ src/view.opa
+
+application_name.model:
+ src/model.opa
7 tools/opa-create/template/mvc/resources/css/style.css
View
@@ -0,0 +1,7 @@
+#main {
+ margin-top: 50px;
+}
+
+textarea {
+ width: 100%;
+}
20 tools/opa-create/template/mvc/src/controller.opa
View
@@ -0,0 +1,20 @@
+resources = @static_resource_directory("resources")
+
+custom = {
+ parser {
+ case r={Server.resource_map(resources)} : r
+ case "/" : Resource.default_redirection_page("/index.html")
+ case "/statistics" : Resource.page("Display", View.statistics())
+ case p=(.*) : path = Text.to_string(p); Resource.page(path, View.page(path))
+ }
+}
+
+Server.start(Server.http, [
+ { register :
+ [ { doctype : { html5 } },
+ { js : [ ] },
+ { css : [ "/resources/css/style.css"] }
+ ]
+ },
+ { ~custom }
+])
27 tools/opa-create/template/mvc/src/model.opa
View
@@ -0,0 +1,27 @@
+type page = {
+ string path,
+ string content,
+ int counter
+}
+
+database application_name {
+ page /page[{path}]
+}
+
+module Model {
+
+ function get_content(path) {
+ /application_name/page[{~path}]/counter++;
+ /application_name/page[{~path}]/content
+ }
+
+ function set_content(path, content) {
+ /application_name/page[{~path}]/content <- content
+ }
+
+ function statistics() {
+ DbSet.iterator(/application_name/page)
+ }
+
+}
+
55 tools/opa-create/template/mvc/src/view.opa
View
@@ -0,0 +1,55 @@
+module View {
+
+ function template(content) {
+ <div class="navbar navbar-fixed-top">
+ <div class="navbar-inner">
+ <div class="container">
+ <a class="brand" href="./index.html">application_name</a>
+ <div class="nav-collapse collapse">
+ <ul class="nav">
+ <li><a href="/statistics">Statistics</a></li>
+ </ul>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div id=#main class="container-fluid">
+ <div class="row-fluid">
+ {content}
+ </div>
+ <hr>
+ <footer>
+ <p>application_name</p>
+ </footer>
+ </div>
+
+ }
+
+ function statistics() {
+ tbody = Iter.fold(
+ function(page, acc) { <>{acc}<tr><td>{page.path}</td><td>{page.counter}</td></tr></> },
+ Model.statistics(), <></>
+ )
+ content =
+ <h3>Page statistics</h3>
+ <table class="table table-bordered">
+ <thead><tr><td>Path</td><td>Counter</td></tr></thead>
+ <tbody>{tbody}</tbody>
+ </table>
+ template(content)
+ }
+
+ function page(path) {
+ content =
+ <div class="hero-unit">
+ <h3>{path}</h3>
+ <textarea id=#content rows="15">{ Model.get_content(path) }</textarea>
+ <button class="btn" onclick={ function(_) Model.set_content(path, Dom.get_value(#content)) }>
+ Save
+ </button>
+ </div>;
+ template(content)
+ }
+
+}
+
19 utils/install.sh
View
@@ -115,7 +115,24 @@ create_wrapper() {
echo "export OCAMLOPT=${OCAMLOPT:-$OCAML_PREFIX/bin/ocamlopt.opt}"
# may need to rewrite $PREFIX/lib/opa/ocaml/lib/ld.conf if ocaml is relocated
fi
- echo 'exec '$source' "$@"'
+ if [ $name = "opa" ]; then
+ echo '
+case "$1" in
+ create)
+ shift
+ if [ -n "$1" ]
+ then
+ OPT="--name $1"
+ fi
+ opa-create $OPT
+ ;;
+ *)
+ exec '$source' "$@"
+esac
+'
+ else
+ echo 'exec '$source' "$@"'
+ fi
} > $wrapper
chmod 755 $wrapper
if [ -n "$LINKDIR" ]; then
Please sign in to comment.
Something went wrong with that request. Please try again.