Permalink
Browse files

[doc] manual: converted all exemples into submodules

  • Loading branch information...
1 parent 1250534 commit 18504bd4408b4720fa0b26b09912d8b7423f2acd @Aqua-Ye Aqua-Ye committed Jul 25, 2012
Showing with 24 additions and 2,257 deletions.
  1. +18 −0 .gitmodules
  2. +1 −0 doc/manual.src/hello-opa
  3. +0 −15 doc/manual.src/hello-opa/.gitignore
  4. +0 −10 doc/manual.src/hello-opa/README.markdown
  5. +0 −18 doc/manual.src/hello-opa/hello-opa.opa
  6. +1 −0 doc/manual.src/hello_chat
  7. +0 −13 doc/manual.src/hello_chat/.gitignore
  8. +0 −10 doc/manual.src/hello_chat/README.markdown
  9. +0 −106 doc/manual.src/hello_chat/hello_chat.opa
  10. +0 −80 doc/manual.src/hello_chat/hello_chat_min.opa
  11. +0 −36 doc/manual.src/hello_chat/resources/chat.css
  12. BIN doc/manual.src/hello_chat/resources/opa-logo.png
  13. BIN doc/manual.src/hello_chat/resources/user.png
  14. +1 −0 doc/manual.src/hello_recaptcha
  15. +0 −14 doc/manual.src/hello_recaptcha/.gitignore
  16. +0 −5 doc/manual.src/hello_recaptcha/Makefile
  17. +0 −14 doc/manual.src/hello_recaptcha/README.markdown
  18. +0 −247 doc/manual.src/hello_recaptcha/hello_recaptcha.opa
  19. +0 −42 doc/manual.src/hello_recaptcha/hello_recaptcha_app.opa
  20. +0 −134 doc/manual.src/hello_recaptcha/hello_recaptcha_test.opa
  21. +0 −35 doc/manual.src/hello_recaptcha/recaptcha.js
  22. +1 −0 doc/manual.src/hello_web_services
  23. +0 −13 doc/manual.src/hello_web_services/.gitignore
  24. +0 −14 doc/manual.src/hello_web_services/README.markdown
  25. +0 −97 doc/manual.src/hello_web_services/hello_wiki_rest.opa
  26. +0 −120 doc/manual.src/hello_web_services/hello_wiki_rest_client.opa
  27. +0 −128 doc/manual.src/hello_web_services/hello_wiki_rest_client_customizable.opa
  28. +0 −13 doc/manual.src/hello_web_services/resources/css.css
  29. BIN doc/manual.src/hello_web_services/resources/opa-logo.png
  30. +1 −0 doc/manual.src/hello_wiki
  31. +0 −13 doc/manual.src/hello_wiki/.gitignore
  32. +0 −10 doc/manual.src/hello_wiki/README.markdown
  33. +0 −146 doc/manual.src/hello_wiki/hello_wiki.opa
  34. +0 −196 doc/manual.src/hello_wiki/hello_wiki_mongo.opa
  35. +0 −142 doc/manual.src/hello_wiki/hello_wiki_simple.opa
  36. +0 −13 doc/manual.src/hello_wiki/resources/css.css
  37. BIN doc/manual.src/hello_wiki/resources/opa-logo.png
  38. +0 −15 doc/manual.src/opa_binding_examples/.gitignore
  39. +0 −13 doc/manual.src/opa_binding_examples/Makefile
  40. +0 −10 doc/manual.src/opa_binding_examples/README.markdown
  41. +0 −18 doc/manual.src/opa_binding_examples/c_binding/Makefile
  42. +0 −2 doc/manual.src/opa_binding_examples/c_binding/c_binding.ml
  43. +0 −54 doc/manual.src/opa_binding_examples/c_binding/freq.c
  44. +0 −2 doc/manual.src/opa_binding_examples/c_binding/freq.opa
  45. +0 −10 doc/manual.src/opa_binding_examples/external_types/Makefile
  46. +0 −37 doc/manual.src/opa_binding_examples/external_types/bigint.ml
  47. +0 −82 doc/manual.src/opa_binding_examples/external_types/bigint.opa
  48. +0 −41 doc/manual.src/opa_binding_examples/hello_bindings.opa
  49. +0 −17 doc/manual.src/opa_binding_examples/opa_types/Makefile
  50. +0 −134 doc/manual.src/opa_binding_examples/opa_types/dbm.ml
  51. +0 −125 doc/manual.src/opa_binding_examples/opa_types/dbm.opa
  52. +0 −9 doc/manual.src/opa_binding_examples/plugin.js
  53. +0 −4 doc/manual.src/opa_binding_examples/plugin.ml
  54. +1 −0 doc/manual.src/opa_bindings_examples
View
18 .gitmodules
@@ -0,0 +1,18 @@
+[submodule "doc/manual.src/opa_bindings_examples"]
+ path = doc/manual.src/opa_bindings_examples
+ url = git@github.com:MLstate/opa_bindings_examples.git
+[submodule "doc/manual.src/hello_recaptcha"]
+ path = doc/manual.src/hello_recaptcha
+ url = git@github.com:MLstate/hello_recaptcha.git
+[submodule "doc/manual.src/hello-opa"]
+ path = doc/manual.src/hello-opa
+ url = git@github.com:MLstate/hello-opa.git
+[submodule "doc/manual.src/hello_wiki"]
+ path = doc/manual.src/hello_wiki
+ url = git@github.com:MLstate/hello_wiki.git
+[submodule "doc/manual.src/hello_web_services"]
+ path = doc/manual.src/hello_web_services
+ url = git@github.com:MLstate/hello_web_services.git
+[submodule "doc/manual.src/hello_chat"]
+ path = doc/manual.src/hello_chat
+ url = git@github.com:MLstate/hello_chat.git
1 doc/manual.src/hello-opa
@@ -0,0 +1 @@
+Subproject commit 8b867abcdb36836383c8fd2ded05a010603dc870
View
15 doc/manual.src/hello-opa/.gitignore
@@ -1,15 +0,0 @@
-*.api
-*.api-txt
-*.log
-opa-debug-js
-*html
-_build
-*.opx
-*.opx.broken
-*.opp
-*.o
-*.dump
-*~
-.DS_Store
-_tracks
-*.exe
View
10 doc/manual.src/hello-opa/README.markdown
@@ -1,10 +0,0 @@
-Summary
--------
-
-This is a very simple demo of Opa. It just shows a header "Hello, world" and upon clicking the header it informs the user how many times it was cliked so far.
-
-Compile and run with:
-
-`opa hello-opa.opa --`
-
-More about this example in Opa manual, chapter [A tour of Opa](http://doc.opalang.org/manual/A-tour-of-Opa).
View
18 doc/manual.src/hello-opa/hello-opa.opa
@@ -1,18 +0,0 @@
-database mydb {
- int /counter = 0;
-}
-
-function action(_) {
- /mydb/counter <- /mydb/counter + 1;
- #msg = <>Hello, user number {/mydb/counter}!</>;
-}
-
-function page() {
- <h1 onclick={action}>Hello, world</h1>
- <div id="msg">Click the header</div>;
-}
-
-Server.start(
- Server.http,
- { ~page, title: "Hello, world" }
-);
1 doc/manual.src/hello_chat
@@ -0,0 +1 @@
+Subproject commit 79f02c75297ea04b2fc9d1129936308c5915426c
View
13 doc/manual.src/hello_chat/.gitignore
@@ -1,13 +0,0 @@
-*.api
-*.api-txt
-*.log
-opa-debug-js
-*html
-_build
-*.opx
-*.opx.broken
-*.dump
-*~
-.DS_Store
-_tracks
-*.exe
View
10 doc/manual.src/hello_chat/README.markdown
@@ -1,10 +0,0 @@
-Summary
--------
-
-This is a chat application written in Opa.
-
-Compile and run with:
-
-`opa hello_chat.opa --`
-
-More about this example in Opa manual, chapter [Hello, chat](http://doc.opalang.org/manual/Hello--chat).
View
106 doc/manual.src/hello_chat/hello_chat.opa
@@ -1,106 +0,0 @@
-/**
- * {1 Import standard classes of bootstrap css}
- *
- * see http://twitter.github.com/bootstrap/
- */
-import stdlib.themes.bootstrap
-
-/**
- * {1 Network infrastructure}
- */
-
-/**
- * The type of messages sent by a client to the chatroom
- */
-type message = { string author /**The name of the author (arbitrary string)*/
- , string text /**Content entered by the user*/
- }
-
-/**
- * The chatroom.
- */
-exposed Network.network(message) room = Network.cloud("room")
-
-/**
- * {1 User interface}
- */
-
-/**
- * Update the user interface in reaction to reception of a message.
- *
- * This function is meant to be registered with [room] as a callback.
- * Its sole role is to display the new message in [#conversation].
- *
- * @param x The message received from the chatroom
- */
-function user_update(message x) {
- line = <div class="row line">
- <div class="span1 columns userpic" />
- <div class="span2 columns user">{x.author}:</div>
- <div class="span13 columns message">{x.text}</div>
- </div>;
- #conversation =+ line;
- Dom.scroll_to_bottom(#conversation);
-}
-
-/**
- * Broadcast text to the [room].
- *
- * Read the contents of [#entry], clear these contents and send the message to [room].
- *
- * @param author The name of the author. Will be included in the message broadcasted.
- */
-function broadcast(author) {
- text = Dom.get_value(#entry);
- message = ~{author, text};
- Network.broadcast(message, room);
- Dom.clear_value(#entry);
-}
-
-/**
- * Build the user interface for a client.
- *
- * Pick a random author name which will be used throughout the chat.
- *
- * @return The user interface, ready to be sent by the server to the client on connection.
- */
-function start() {
- author = Random.string(8);
- <div class="navbar navbar-fixed-top">
- <div class="navbar-inner">
- <div class="container">
- <div id=#logo />
- </>
- </>
- </>
- <div id=#conversation class="container"
- onready={function(_) { Network.add_callback(user_update, room) }}></>
- <div id=#footer class="navbar navbar-fixed-bottom">
- <div class="container">
- <div class="input-append">
- <input id=#entry class="input-xlarge" type="text"
- onnewline={function(_) { broadcast(author) }}>
- <button class="btn btn-primary" type="button" onclick={function(_) { broadcast(author) }}>Post</button>
- </>
- </>
- </>
-}
-
-/**
- * {1 Application}
- */
-
-/**
- * Main entry point.
- *
- * Construct an application called "Chat" (users will see the name in the title bar),
- * embedding statically the contents of directory "resources", using the global stylesheet
- * "resources/chat.css" and the user interface defined in [start].
- */
-Server.start(
- Server.http,
- [ { resources: @static_resource_directory("resources") }
- , { register: { css: ["resources/chat.css"] } }
- , { title: "Chat", page: start }
- ]
-);
View
80 doc/manual.src/hello_chat/hello_chat_min.opa
@@ -1,80 +0,0 @@
-/**
- * Minimal version of hello_chat
- * - no style
- * - no @publish
- */
-
-/**
- * {1 Network infrastructure}
- */
-
-/**
- * The type of messages sent by a client to the chatroom
- */
-type message = { string author /**The name of the author (arbitrary string)*/
- , string text /**Content entered by the user*/
- }
-
-/**
- * The chatroom.
- */
-room = Network.network(message) (Network.cloud("room"))
-
-/**
- * {1 User interface}
- */
-
-/**
- * Update the user interface in reaction to reception of a message.
- *
- * This function is meant to be registered with [room] as a callback.
- * Its sole role is to display the new message in [#conversation].
- *
- * @param x The message received from the chatroom
- */
-function user_update(message x) {
- line = <div>{x.author}: {x.text}</div>;
- #conversation =+ line;
- Dom.scroll_to_bottom(#conversation);
-}
-
-/**
- * Broadcast text to the [room].
- *
- * Read the contents of [#entry], clear these contents and send the message to [room].
- *
- * @param author The name of the author. Will be included in the message broadcasted.
- */
-function broadcast(author) {
- text = Dom.get_value(#entry);
- message = ~{author, text};
- Network.broadcast(message, room);
- Dom.clear_value(#entry);
-}
-
-/**
- * Build the user interface for a client.
- *
- * Pick a random author name which will be used throughout the chat.
- *
- * @return The user interface, ready to be sent by the server to the client on connection.
- */
-function start() {
- author = Random.string(8);
- <div id=#conversation onready={function(_) { Network.add_callback(user_update, room) }} />
- <input id=#entry onnewline={function(_) { broadcast(author) }} />
- <input type="button" onclick={function(_) { broadcast(author) }} value="Post" />;
-}
-
-/**
- * {1 Application}
- */
-
-/**
- * Main entry point.
- *
- * Construct an application called "Chat" (users will see the name in the title bar),
- * embedding statically the contents of directory "resources", using the global stylesheet
- * "resources/css.css" and the user interface defined in [start].
- */
-Server.start(Server.http, {title: "Chat", page: start });
View
36 doc/manual.src/hello_chat/resources/chat.css
@@ -1,36 +0,0 @@
-/***Header***/
-#logo {
- background: url("/resources/opa-logo.png") no-repeat scroll 0 0 transparent;
- height: 32px;
- margin: 10px 0 5px;
- width: 61px;
-}
-
-/***Conversation***/
-#conversation {
- overflow:auto;
- position: absolute;
- margin: auto;
- bottom: 48px;
- top: 50px;
- left: 0;
- right: 0;
-}
-.line {
- border-bottom:1px solid #ddd;
- padding-bottom:8px;
- margin-bottom:8px !important;
-}
-.user, .message {padding-top:8px;}
-.userpic {
- background: url("/resources/user.png") no-repeat 0 0;
- height: 40px;
- width:40px;
-}
-.user {color: #000;font-weight:bold;}
-.message{color:#666;}
-
-/***Footer***/
-#footer {
- background:#eee;
-}
View
BIN doc/manual.src/hello_chat/resources/opa-logo.png
Deleted file not rendered
View
BIN doc/manual.src/hello_chat/resources/user.png
Deleted file not rendered
1 doc/manual.src/hello_recaptcha
@@ -0,0 +1 @@
+Subproject commit e09e76c9328a82c3328f2b55a48a0f04893cb0ae
View
14 doc/manual.src/hello_recaptcha/.gitignore
@@ -1,14 +0,0 @@
-*.api
-*.api-txt
-*.log
-opa-debug-js
-*html
-_build
-*.opx
-*.opx.broken
-*.opp
-*.dump
-*~
-.DS_Store
-_tracks
-*.exe
View
5 doc/manual.src/hello_recaptcha/Makefile
@@ -1,5 +0,0 @@
-hello_recaptcha_app.exe: recaptcha.opp hello_recaptcha.opa hello_recaptcha_app.opa
- $(OPA) $^
-
-recaptcha.opp: recaptcha.js
- $(OPA_PLUGIN_BUILDER) recaptcha.js -o recaptcha
View
14 doc/manual.src/hello_recaptcha/README.markdown
@@ -1,14 +0,0 @@
-Summary
--------
-
-This is an example of binding external JavaScript library (here, reCaptcha) in Opa.
-
-Compile with:
-
-`make`
-
-Run with:
-
-`./hello_recaptcha_app.exe`
-
-More about this example in Opa manual, chapter [Hello, reCaptcha, and the rest of the world](http://doc.opalang.org/manual/Hello--reCaptcha--and-the-rest-of-the-world).
View
247 doc/manual.src/hello_recaptcha/hello_recaptcha.opa
@@ -1,247 +0,0 @@
-package tutorial.recaptcha
-
-import stdlib.web.client
-
-/**
- * A user interface component based on Google reCaptcha, used to differenciate between
- * human beings and spam/link harvest bots by confronting users to read words from scanned
- * books.
- *
- * This module implements a very thin layer on top of the Google reCaptcha AJAX API.
- * For more information on reCaptcha API, see {{:http://code.google.com/apis/recaptcha/intro.html} the official
- * documentation}.
- */
-
-/**
- * {1 Types defined in this module}
- */
-
-/**
- * {2 Setting up the recaptcha}
- */
-
-/**
- * A configuration for the captcha.
- */
-
-type Recaptcha.config =
-{
- {
- /**
- * The private access key to the service.
- *
- * Obtain one (and the corresponding public key) from {{:https://www.google.com/recaptcha/admin/create} reCaptcha}
- */
- string privkey
- }
- /**
- * Private fields, isolated for clarity: for security reasons, content of these fields
- * must never be sent to the client.
- */
- cfg_private,
-
- {
- /**
- * The public access key to the service.
- *
- * Obtain one (and the corresponding private key) from {{:https://www.google.com/recaptcha/admin/create} reCaptcha}
- */
- string pubkey,
-
- /**
- * Name of the visual theme to use for this captcha.
- *
- * If [{none}], we default to the "red" style. Other acceptable styles are: "white", "blackglass",
- * "clean" or "custom". For more details, see the {{:http://code.google.com/apis/recaptcha/docs/customization.html}
- * reCaptcha customization manual}.
- */
- option(string) theme
- }
- /**
- * Public fields, isolated for clarity: the content of these fields can be shared with
- * the client without causing any security issue.
- */
- cfg_public
-}
-
-/**
- * {2 The reCaptcha object}
- */
-
-/**
- * An abstract object implementing the methods of the reCaptcha.
- */
-abstract type Recaptcha.implementation = {
- /**Place a request to the reCaptcha server to verify that user entry is correct.
- @param challenge
- @param response
- @param callback*/
- (string, string, (Recaptcha.result -> void) -> void) validate,
- /**Reload the reCaptcha, displaying a different challenge*/
- (-> void) reload,
- /**Destroy the reCaptcha*/
- (-> void) destroy
-}
-
-/**
- * {2 Manipulation of recapatcha results}
- */
-type Recaptcha.success = {captcha_solved} /**The captcha is correct.*/
-type Recaptcha.failure =
- {WebClient.failure captcha_not_reachable} /**Could not reach the distant server.*/
- or {string upstream} /**Upstream error, documented but left unspecified by Google.*/
- or {list(string) unknown} /**Server could be reached, but produced an error that doesn't match the specifications provided by Google.
- Possible cause: proxy problem.*/
- or {empty_answer} /**Recaptcha guidelines mention that we should never send answers that are empty.*/
-
-type Recaptcha.result = {Recaptcha.success success} or {Recaptcha.failure failure}
-
-/**
- * {1 Implementation}
- */
-
-module Recaptcha
-{
- /**
- * Construct a reCaptcha.
- *
- * Note: The API provided by Google only permits one reCaptcha per page.
- *
- * @param config The configuration for the recaptcha. Note that, as this configuration
- * contains security-sensitive information, it {e must} be stored on the server.
- *
- * @return An object representing the methods of the reCaptcha, which you can later use
- * to validate an entry, reload the reCaptcha, etc. and a [xhtml] extract which should be
- * inserted in a page to display the captcha dialog.
- */
- function (Recaptcha.implementation, xhtml) make(Recaptcha.config config) {
- id = Dom.fresh_id();
- xhtml = <div id={id} onready={function(_) { onready(id, config.cfg_public.pubkey, config.cfg_public.theme?"red") }}/>;
- (make_implementation(config.cfg_private.privkey), xhtml);
- }
-
- /**
- * Attempt to determine whether a user is a human being.
- *
- * This request calls upon Google's reCaptcha servers to determine whether
- * the user is probably a human being.
- *
- * @param implementation A reCaptcha.
- * @param callback A function which will be called once the server has provided an answer
- */
- function void validate(Recaptcha.implementation implementation, (Recaptcha.result -> void) callback) {
- t = get_token();
- implementation.validate(t.challenge, t.response, callback);
- }
-
- /**
- * Display a new challenge
- *
- * @param implementation A reCaptcha.
- */
- function void reload(Recaptcha.implementation implementation) {
- implementation.reload();
- }
-
- /**
- * Clean-up and remove the reCaptcha.
- *
- * If you are using the reCaptcha in a dialog box, it is generally a good idea to call
- * this function if the user closes the box.
- *
- * @param implementation A reCaptcha.
- */
- function void destroy(Recaptcha.implementation implementation) {
- implementation.destroy();
- }
-
- /**
- * {2 Private implementation details}
- */
-
- /**
- * The URIs for the API
- */
-
- private path_validate_uri =
- Option.get(Parser.try_parse(Uri.uri_parser, "http://www.google.com/recaptcha/api/verify"))
-
- private path_js_uri =
- Option.get(Parser.try_parse(Uri.uri_parser, "http://www.google.com/recaptcha/api/js/recaptcha_ajax.js"))
-
- /**
- * Perform client-side delayed initialization.
- *
- * Load the reCaptcha script if necessary, then perform script initialization.
- *
- * @param id The dom identifier of the xhtml component which will contain the reCaptcha.
- * @param pubkey The public key for this reCaptcha.
- * @param theme The name of the theme for this reCaptcha (in case of doubt, "red" is a good choice).
- */
- private function void onready(string id, string pubkey, string theme) {
- Client.Script.load_uri_then(path_js_uri,
- function(){
- (%% Recaptcha.init %%)(id, pubkey, theme);
- }
- )
- }
-
- private cl_reload =
- %%Recaptcha.reload%% /**Implementation of [reload]*/
-
- private cl_destroy =
- %%Recaptcha.destroy%% /**Implementation of [destroy]*/
-
- /**
- * Construct the object representing the reCaptcha
- *
- * @param privkey The private key.
- * @return An object containing the necessary methods to contact the reCaptcha server.
- */
- private function Recaptcha.implementation make_implementation(string privkey) {
- function validate(challenge, response, (Recaptcha.result -> void) callback) {
- //By convention, do not even post a request if the data is empty
- if (String.is_empty(challenge) || String.is_empty(response)) {
- callback({failure: {empty_answer}});
- } else {
- /**POST request, formatted as per API specifications*/
- data = [ ("privatekey", privkey)
- , ("remoteip", "{HttpRequest.get_ip()?(127.0.0.1)}")
- , ("challenge", challenge)
- , ("response", response)
- ];
- /**Handle POST failures, decode reCaptcha responses, convert this to [reCaptcha.result].*/
- function with_result(res) {
- match (res) {
- case ~{failure}:
- callback({failure: {captcha_not_reachable: failure}});
- case ~{success}:
- details = String.explode("\n", success.content);
- match (details) {
- case ["true" | _]: callback({success: {captcha_solved}});
- case ["false", code | _]: callback({failure: {upstream: code}});
- default: callback({failure: {unknown: details}});
- }
- }
- }
- /**Encode arguments, POST them*/
- WebClient.Post.try_post_with_options_async(path_validate_uri,
- WebClient.Post.of_form({WebClient.Post.default_options with content: {some: data}}),
- with_result);
- }
- }
- {~validate, reload:cl_reload, destroy:cl_destroy};
- }
-
- /**
- * Grab all necessary information from the user interface.
- */
- private function {string challenge, string response} get_token() {
- result = ({ challenge: (%%Recaptcha.get_challenge%%)()
- , response: (%%Recaptcha.get_response%%)()
- });
- (%%Recaptcha.destroy%%)();
- result;
- }
-
-}
View
42 doc/manual.src/hello_recaptcha/hello_recaptcha_app.opa
@@ -1,42 +0,0 @@
-import tutorial.recaptcha
-
-/**
- * A test configuration for the reCaptcha, based on a public/private key pair
- * registered for "example.com".
- */
-server protected config =
-{
- cfg_private: {
- privkey: "6LdVTcQSAAAAAJGuyHbunFigtJ1HuI1nkVtwAahg"
- },
- cfg_public: {
- pubkey: "6LdVTcQSAAAAABMAPRuRawMTsX0vfW2O2c3bDeeL",
- theme: {some: "red"}
- }
-}
-
-/**
- * After validation, just display the result.
- */
-function after_validation(res) {
- match (res) {
- case { success: _ }: #status = <>success</>;
- case { failure: _ }: #status = <>failure</>;
- }
-}
-
-function page() {
- (implementation, recaptcha) = Recaptcha.make(config);
- <div>
- Are you a human being?<br />
- {recaptcha}
- <button onclick={function(_) { Recaptcha.validate(implementation, after_validation)}}> Submit </button>
- <div id=#status></div>
- </div>;
-}
-
-/**
- * Main application.
- */
-Server.start(Server.http, {title: "Hello, Recaptcha", ~page});
-
View
134 doc/manual.src/hello_recaptcha/hello_recaptcha_test.opa
@@ -1,134 +0,0 @@
-/*
- Copyright © 2011, 2012 MLstate
-
- This file is part of Opa.
-
- 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.
-*/
-//Implement [Client.load]
-//reCaptcha: api/recaptcha
-
-bug = {true} //Replace by {false} to obtain something that works
-
-
-type Recaptcha.success = {captcha_solved}
-type Recaptcha.failure =
- {captcha_not_reachable}
- / {upstream: string} /**Upstream error, code may be used for debugging purposes.*/
- / {unknown: list(string)}
- / {empty_answer}
-
-type Recaptcha.result = {success: Recaptcha.success} / {failure: Recaptcha.failure}
-
-type Recaptcha.config =
-{
- private:
- {
- privkey: string
- }
- public:
- {
- pubkey: string
- theme: option(string)
- }
-}
-
-type Recaptcha.validator = private((string, string, (Recaptcha.result -> void) -> void))
-
-Recaptcha =
-{{
- make(config: Recaptcha.config): (Recaptcha.validator, xhtml) =
- (
- id = Dom.fresh_id()
- xhtml = <div id={id} onready={_ -> onready(id, config.public.pubkey, config.public.theme?"red")}/>
- (validator(config.private.privkey), xhtml)
- )
-
- validate(validator: Recaptcha.validator, callback: Recaptcha.result -> void): void =
- (
- (a, b) = get_token()
- @unwrap(validator)(a, b, callback)
- )
-
- @private path_api_uri = Option.get(Parser.try_parse(Uri.uri_parser, "http://www.google.com/recaptcha/api/verify"))
- @private path_js = "http://www.google.com/recaptcha/api/js/recaptcha_ajax.js"
-
- @private onready(id: string, pubkey: string, theme: string): void =
- (
- do Log.info("onready", "start")
- Client.Script.load_from_then(path_js, ->
- do Log.info("onready", "loaded")
- do (%% Recaptcha.init %%)(id, pubkey, theme)
- do Log.info("onready", "initialized")
- void
- )
- )
- @private validator(privkey: string): Recaptcha.validator =
- (
- payload(challenge, response, callback:Recaptcha.result -> void) =
- (
- if String.is_empty(challenge) || String.is_empty(response) then callback({failure = {empty_answer}})
- else
- (
- data = [("privatekey", privkey),
- ("remoteip", "{HttpRequest.get_ip(Option.get(thread_context().request))}"),
- ("challenge", challenge),
- ("response", response)]
- with_result =
- (
- | {failure = _} -> callback({failure = {captcha_not_reachable}})
- | ~{success} ->
- details = String.explode("\n", success.content)
- match details with
- | ["true" | _] -> callback({success = {captcha_solved}})
- | ["false", code | _] -> callback({failure = {upstream = code}})
- | _ -> callback({failure = {unknown = details}})
- )
- if bug then WebClient.Post.try_post_with_options_async(path_api_uri,
- WebClient.Post.of_form({WebClient.Post.default_options with content = {some = data}}),
- with_result) // <= this version doesn't work, callback is called but cannot perform server->client calls
- else
- with_result(WebClient.Post.try_post_with_options(path_api_uri,
- WebClient.Post.of_form({WebClient.Post.default_options with content = {some = data}})))
- // <= this version works, callback is called but cannot perform server->client calls
- )
- )
- @wrap(payload)
- )
- @private get_token(): (string, string) =
- (
- result = ((%%Recaptcha.get_challenge%%)(), (%%Recaptcha.get_response%%)())
- do (%%Recaptcha.destroy%%)()
- result
- )
-}}
-
-config = {
- private = {
- privkey = "6LeeR8QSAAAAADSnODF238nFuhfPQ13OH9sMib6o"
- }
- public = {
- pubkey = "6LeeR8QSAAAAANEPtPmwgSATS64g1p4qOg0fpEJH"
- theme = {some = "red"}
- }
-}
-
-after_validation =
- | {success = _} ->
- do Log.info("Success", "success")
- Dom.transform([#status <- <>success</>])
- | {~failure} -> do Log.info("Failure", failure)
- Dom.transform([#status <- <>failure</>])
-
-server = one_page_server("Hi", ->
- (validator, recaptcha) = Recaptcha.make(config)
- <div>
- {recaptcha}
- <button onclick={_ -> Recaptcha.validate(validator, after_validation)} > Submit </button>
- <div id=#status></div>
- </div>
-)
View
35 doc/manual.src/hello_recaptcha/recaptcha.js
@@ -1,35 +0,0 @@
-##register init: string, string, string -> void
-##args(id, pubkey, theme)
-{
- Recaptcha.create(pubkey,
- id,
- {
- theme: theme,
- callback: Recaptcha.focus_response_field
- }
- );
-}
-
-##register get_challenge: -> string
-##args()
-{
- return (Recaptcha.get_challenge()||"")
-}
-
-##register get_response: -> string
-##args()
-{
- return (Recaptcha.get_response()||"")
-}
-
-##register destroy: -> void
-##args()
-{
- Recaptcha.destroy();
-}
-
-##register reload: -> void
-##args()
-{
- Recaptcha.reload();
-}
1 doc/manual.src/hello_web_services
@@ -0,0 +1 @@
+Subproject commit 4380cd59553eb95dad606973d59d96ebf2d66ec5
View
13 doc/manual.src/hello_web_services/.gitignore
@@ -1,13 +0,0 @@
-*.api
-*.api-txt
-*.log
-opa-debug-js
-*html
-_build
-*.opx
-*.opx.broken
-*.dump
-*~
-.DS_Store
-_tracks
-*.exe
View
14 doc/manual.src/hello_web_services/README.markdown
@@ -1,14 +0,0 @@
-Summary
--------
-
-This is an example of using web services (both from the client and the server perspective) in Opa.
-
-Compile and run the server with:
-
-`opa hello_wiki_rest.opa --`
-
-Compile and run the client with:
-
-`opa hello_wiki_rest_client_customizable.opa --`
-
-More about this example in Opa manual, chapter [Hello, web services](http://doc.opalang.org/manual/Hello--web-services).
View
97 doc/manual.src/hello_web_services/hello_wiki_rest.opa
@@ -1,97 +0,0 @@
-import stdlib.tools.markdown
-import stdlib.themes.bootstrap
-
-database stringmap(string) /wiki
-database /wiki[_] = "This page is empty. Double click to edit"
-
-function load_source(topic) {
- /wiki[topic];
-}
-
-exposed function load_rendered(topic) {
- source = load_source(topic);
- Markdown.xhtml_of_string(Markdown.default_options, source);
-}
-
-exposed function save_source(topic, source) {
- /wiki[topic] <- source;
- load_rendered(topic);
-}
-
-exposed function remove_topic(topic) {
- Db.remove(@/wiki[topic]);
-}
-
-function edit(topic) {
- Dom.set_value(#edit_content, load_source(topic));
- Dom.hide(#show_content);
- Dom.show(#edit_content);
- Dom.give_focus(#edit_content);
-}
-
-function save(topic) {
- content = save_source(topic, Dom.get_value(#edit_content));
- #show_content = content;
- Dom.hide(#edit_content);
- Dom.show(#show_content);
-}
-
-function display(topic) {
- Resource.styled_page("About {topic}", ["/resources/css.css"],
- <div class="navbar navbar-fixed-top">
- <div class="navbar-inner">
- <div class="container">
- <span id=#logo class="brand"/><span class="navbar-text">About {topic}</span>
- </div>
- </div>
- </div>
- <div class="content container">
- <div class="show_content" id=#show_content ondblclick={function(_) { edit(topic) }}>
- {load_rendered(topic)}
- </div>
- </div>
- <textarea class="edit_content" id=#edit_content style="display:none"
- cols="40" rows="30" onblur={function(_) { save(topic) }}></>
- );
-}
-
-function rest(topic) {
- match (HttpRequest.get_method()) {
- case {some: method} :
- match (method) {
- case {post}:
- _ = save_source(topic, HttpRequest.get_body() ? "");
- Resource.raw_status({success});
- case {delete}:
- remove_topic(topic);
- Resource.raw_status({success});
- case {get}:
- Resource.raw_response(load_source(topic), "text/plain", {success});
- default:
- Resource.raw_status({method_not_allowed});
- }
- default:
- Resource.raw_status({bad_request});
- }
-}
-
-function topic_of_path(path) {
- String.capitalize(
- String.to_lower(List.to_string_using("", "", "::", path))
- );
-}
-
-function start(url) {
- match (url) {
- case {path: [] ... }: display("Hello");
- case {path: ["_rest_" | path] ...}: rest(topic_of_path(path));
- case {~path ...}: display(topic_of_path(path));
- }
-}
-
-Server.start(
- Server.http,
- [ {resources: @static_include_directory("resources")}
- , {dispatch: start}
- ]
-)
View
120 doc/manual.src/hello_web_services/hello_wiki_rest_client.opa
@@ -1,120 +0,0 @@
-import stdlib.tools.markdown
-import stdlib.themes.bootstrap
-
-function uri_for_topic(topic) {
- Uri.of_absolute(
- {Uri.default_absolute with
- schema : {some: "http"},
- domain : "localhost",
- port : {some: 8080},
- path : ["_rest_", topic]
- }
- )
-}
-
-function load_source(topic) {
- match (WebClient.Get.try_get(uri_for_topic(topic))) {
- case { failure : _ }: "Error, could not connect";
- case ~{ success }:
- match (WebClient.Result.get_class(success)) {
- case { success }: success.content;
- default: "Error {success.code}";
- }
- }
-}
-
-exposed function load_rendered(topic) {
- source = load_source(topic);
- Markdown.xhtml_of_string(Markdown.default_options, source);
-}
-
-exposed function save_source(topic, source) {
- match (WebClient.Post.try_post(uri_for_topic(topic), source)) {
- case { failure: _ }: {failure: "Could not reach the distant server"};
- case { success: s }:
- match (WebClient.Result.get_class(s)) {
- case { success }: {success : load_rendered(topic)};
- default: {failure : "Error {s.code}"};
- }
- }
-}
-
-function remove_topic(topic) {
- _ = WebClient.Delete.try_delete(uri_for_topic(topic));
- void;
-}
-
-function edit(topic) {
- #show_messages = <></>;
- Dom.set_value(#edit_content, load_source(topic));
- Dom.hide(#show_content);
- Dom.show(#edit_content);
- Dom.give_focus(#edit_content);
-}
-
-function save(topic) {
- match (save_source(topic, Dom.get_value(#edit_content))) {
- case { ~success }:
- #show_content = success;
- Dom.hide(#edit_content);
- Dom.show(#show_content);
- case {~failure}:
- #show_messages = <>{failure}</>;
- }
-}
-
-function display(topic) {
- Resource.styled_page(
- "About {topic}", ["/resources/css.css"],
- <div class="navbar navbar-fixed-top">
- <div class="navbar-inner">
- <div class="container">
- <span id=#logo class="brand"/><span class="navbar-text">About {topic}</span>
- </div>
- </div>
- </div>
- <div class="content container">
- <div class="show_content" id=#show_content ondblclick={function(_) { edit(topic) }}>{load_rendered(topic)}</div>
- </div>
- <div class="show_messages" id=#show_messages />
- <textarea class="edit_content" id=#edit_content style="display:none" cols="40" rows="30" onblur={function(_) { save(topic) }}></>
- );
-}
-
-function rest(topic) {
- match (HttpRequest.get_method()) {
- case {some: method}:
- match (method) {
- case { post }:
- _ = save_source(topic, `?`(HttpRequest.get_body(), ""));
- Resource.raw_status({success});
- case { delete }: remove_topic(topic);
- Resource.raw_status({success});
- case { get }: Resource.source(load_source(topic), "text/plain");
- default: Resource.raw_status({method_not_allowed});
- }
- default: Resource.raw_status({bad_request});
- }
-}
-
-function topic_of_path(path) {
- String.capitalize(
- String.to_lower(List.to_string_using("", "", "::", path))
- );
-}
-
-function start(url) {
- match (url) {
- case { path : [], ... }: display("Hello");
- case { path : ["rest" | path], ... }: rest(topic_of_path(path));
- case ~{ path, ... }: display(topic_of_path(path));
- }
-
-}
-
-Server.start(
- Server.http,
- [ {resources: @static_include_directory("resources")}
- , {dispatch: start}
- ]
-)
View
128 doc/manual.src/hello_web_services/hello_wiki_rest_client_customizable.opa
@@ -1,128 +0,0 @@
-import stdlib.tools.markdown
-
-uri_for_topic =
- domain_parser =
- {CommandLine.default_parser with
- names: ["--wiki-server-domain"],
- description: "The REST server for this wiki. By default, localhost.",
-// FIXME, | after parser should not be needed
- function on_param(x) { parser { case y=Rule.consume : {no_params: {x with domain: y}}} }
- }
- port_parser =
- {CommandLine.default_parser with
- names: ["--wiki-server-port"],
- description: "The server port of the REST server for this wiki. By default, 8080.",
- function on_param(x) { parser { case y=Rule.natural : {no_params: {x with port: {some: y}}}} }
- }
- base_uri =
- CommandLine.filter(
- {title : "Wiki arguments",
- init : {Uri.default_absolute with domain: "localhost", schema: {some: "http"}},
- parsers : [domain_parser, port_parser],
- anonymous : []
- }
- )
- function(topic) {
- Uri.of_absolute({base_uri with path: ["_rest_", topic]});
- }
-
-exposed function load_source(topic) {
- match (WebClient.Get.try_get(uri_for_topic(topic))) {
- case { failure : _ }: "Error, could not connect";
- case ~{ success }:
- match (WebClient.Result.get_class(success)) {
- case { success }: success.content;
- default: "Error {success.code}";
- }
- }
-}
-
-exposed function load_rendered(topic) {
- source = load_source(topic);
- Markdown.xhtml_of_string(Markdown.default_options, source);
-}
-
-exposed function save_source(topic, source) {
- match (WebClient.Post.try_post(uri_for_topic(topic), source)) {
- case { failure : _ }: {failure : "Could not reach the distant server"}
- case { success : s }:
- match (WebClient.Result.get_class(s)) {
- case { success }: {success : load_rendered(topic)};
- default: {failure : "Error {s.code}"};
- }
- }
-}
-
-function remove_topic(topic) {
- _ = WebClient.Delete.try_delete(uri_for_topic(topic))
- void
-}
-
-function edit(topic) {
- #show_messages = <></>;
- Dom.set_value(#edit_content, load_source(topic));
- Dom.hide(#show_content);
- Dom.show(#edit_content);
- Dom.give_focus(#edit_content);
-}
-
-function save(topic) {
- match (save_source(topic, Dom.get_value(#edit_content))) {
- case ~{ success }:
- #show_content = success;
- Dom.hide(#edit_content);
- Dom.show(#show_content);
- case ~{ failure}:
- #show_messages = <>{failure}</>;
- }
-}
-
-function display(topic) {
- Resource.styled_page("About {topic}", ["/resources/css.css"],
- <div id=#header><div id=#logo></div>About {topic}</div>
- <div class="show_content" id=#show_content ondblclick={function(_) { edit(topic) }}>{load_rendered(topic)}</>
- <div class="show_messages" id=#show_messages />
- <textarea class="edit_content" id=#edit_content style="display:none" cols="40" rows="30" onblur={function(_) { save(topic) }}></>
- )
-}
-
-function rest(topic) {
- match (HttpRequest.get_method()) {
- case {some: method}:
- match (method) {
- case { post }:
- _ = save_source(topic, HttpRequest.get_body()?"")
- Resource.raw_status({success});
- case { delete }:
- remove_topic(topic);
- Resource.raw_status({success});
- case { get }:
- Resource.source(load_source(topic), "text/plain");
- default:
- Resource.raw_status({method_not_allowed});
- }
- default: Resource.raw_status({bad_request})
- }
-}
-
-function topic_of_path(path) {
- String.capitalize(
- String.to_lower(List.to_string_using("", "", "::", path))
- );
-}
-
-function start(url) {
- match (url) {
- case { path : [], ... }: display("Hello");
- case { path : ["rest" | path], ... }: rest(topic_of_path(path));
- case ~{ path, ... }: display(topic_of_path(path));
- }
-
-}
-
-Server.start(
- Server.http,
- [ {resources: @static_include_directory("resources")}
- , {dispatch: start}
- ]
-);
View
13 doc/manual.src/hello_web_services/resources/css.css
@@ -1,13 +0,0 @@
-/***Header***/
-#logo {
- background: url("/resources/opa-logo.png") no-repeat scroll 0 0 transparent;
- height: 32px;
- margin: 7px 0 -15px;
- width: 61px;
-}
-/***Editing area***/
-.content {margin-top:60px;}
-#edit_content {
- width:100%;
- display: none; /* initially hidden */
-}
View
BIN doc/manual.src/hello_web_services/resources/opa-logo.png
Deleted file not rendered
1 doc/manual.src/hello_wiki
@@ -0,0 +1 @@
+Subproject commit 5244c11aab056f4d66a826af3da400af67550465
View
13 doc/manual.src/hello_wiki/.gitignore
@@ -1,13 +0,0 @@
-*.api
-*.api-txt
-*.log
-opa-debug-js
-*html
-_build
-*.opx
-*.opx.broken
-*.dump
-*~
-.DS_Store
-_tracks
-*.exe
View
10 doc/manual.src/hello_wiki/README.markdown
@@ -1,10 +0,0 @@
-Summary
--------
-
-This is a simple wiki implemented in Opa.
-
-Compile and run with:
-
-`opa hello_wiki.opa --`
-
-More about this example in Opa manual, chapter [Hello, wiki](http://doc.opalang.org/manual/Hello--wiki).
View
146 doc/manual.src/hello_wiki/hello_wiki.opa
@@ -1,146 +0,0 @@
-/**
- * {1 Import standard classes of bootstrap css}
- *
- * see http://twitter.github.com/bootstrap/
- */
-import stdlib.themes.bootstrap
-
-/**
- * {1 Import markdown syntax}
- */
-import stdlib.tools.markdown
-
-/**
- * {1 Database and database interaction}
- */
-
-/**
- * Contents of the wiki.
- *
- * Pages which do not exist have content "This page is empty".
- */
-database stringmap(string) /wiki
-database /wiki[_] = "This page is empty. Double-click to edit."
-
-/**
- * Read the content associated to a topic from the database and return the
- * corresponding Markdown source.
- *
- * @param topic A topic (arbitrary string).
- * @return If a page has been saved in for [topic], the source for this
- * page. Otherwise, the source for the default page.
- */
-function load_source(topic) {
- /wiki[topic];
-}
-
-/**
- * Read the content associated to a topic from the database and return the
- * corresponding xhtml, ready to insert.
- *
- * @param topic A topic (arbitrary string).
- * @return If a page has been saved in for [topic], the xhtml for this
- * page. Otherwise, the xhtml for the default page.
- *
- * Note: This function does not perform any caching.
- * Note: This function is exposed because a user can ask the rendered content for any topic.
- */
-exposed function load_rendered(topic) {
- source = load_source(topic);
- Markdown.xhtml_of_string(Markdown.default_options, source);
-}
-
-/**
- * Accept source and save the corresponding document in the database.
- *
- * @param topic A topic (arbitrary string).
- * @param source Markdown source to store at this topic.
- * @return The xhtml for the page that has just been saved.
- *
- * Note: This function is exposed because a user can save any content for any topic.
- */
-exposed function save_source(topic, source) {
- /wiki[topic] <- source;
- load_rendered(topic);
-}
-
-/**
- * {1 User interface}
- */
-
-/**
- * Set the user interface in edition mode.
- *
- * Load the Markdown source for a topic, display an editable zone
- * for this markdown.
- *
- * @param topic The topic to edit.
- */
-function edit(topic) {
- Dom.set_value(#edit_content, load_source(topic));
- Dom.hide(#show_content);
- Dom.show(#edit_content);
- Dom.give_focus(#edit_content);
-}
-
-/**
- * Set the user interface in reading mode.
- *
- * Save the Markdown source for a topic (extracted from [#edit_content]),
- * display the rendered version.
- *
- * @param topic The topic to save.
- */
-function save(topic) {
- content = save_source(topic, Dom.get_value(#edit_content));
- #show_content = content;
- Dom.hide(#edit_content);
- Dom.show(#show_content);
-}
-
-/**
- * Main user interface
- *
- * @param topic The topic being consulted
- * @return A resource, ready to be passed to a dispatcher.
- */
-function display(topic) {
- xhtml =
- <div class="navbar navbar-fixed-top"><div class="navbar-inner"><div class="container"><div id=#logo></div></div></div></div>
- <div class="content container">
- <div class="page-header"><h1>About {topic}</></>
- <div class="well" id=#show_content ondblclick={function(_) { edit(topic) }}>{load_rendered(topic)}</>
- <textarea rows="30" id=#edit_content onblur={function(_) { save(topic) }}></>
- </div>;
- Resource.styled_page("About {topic}", ["/resources/css.css"], xhtml);
-}
-
-/**
- * {1 Main application}
- */
-
-/**
- * Dispatch requests to the user interface
- *
- * Note: The empty request is dispatched as if it were "Hello".
- */
-function start(url) {
- match (url) {
- case {path:[] ... } :
- display("Hello");
- case {~path ...} :
- display(String.capitalize(String.to_lower(String.concat("::", path))));
- }
-}
-
-/**
- * Start the wiki server
- */
-Server.start(
- Server.http,
- /** Statically embed a bundle of resources */
- [ {resources: @static_include_directory("resources")}
- /** Launch the [start] dispatcher */
- , {dispatch: start}
- ]
-);
View
196 doc/manual.src/hello_wiki/hello_wiki_mongo.opa
@@ -1,196 +0,0 @@
-/**
- * {1 Import the high-level MongoDB API module}
- *
- * For the low-level API see the package stdlib.apis.mongo
- */
-import stdlib.apis.{mongo}
-
-/**
- * {1 Import standard classes of bootstrap css}
- *
- * see http://twitter.github.com/bootstrap/
- */
-import stdlib.themes.bootstrap
-
-/**
- * {1 Import templates}
- */
-import stdlib.web.template
-
-/**
- * {1 Database and database interaction}
- */
-
-/**
- * The basic info. about the database and table location.
- */
-type page = {
- _id : string;
- _rev : Bson.int32;
- content : string;
-}
-
-/**
- * We work at level 1, run-time type-checked storage of a collection of OPA values.
- *
- * The Mongo.pkg type provides convenience functions for building select and update documents.
- **/
-(wiki_collection,wiki_pkg) = (MongoCollection.openpkgfatal("default","db","wiki"):Mongo.pkg(page))
-pageselect(v) = wiki_pkg.select(Bson.opa2doc(v))
-pageupdate(v) = wiki_pkg.update(Bson.opa2doc(v))
-
-/**
- * Indexes aren't automatic in MongoDB apart from the non-removable _id index.
- * Since we're searching on _rev as well, we need a separate index.
- **/
-_ = MongoCollection.create_index(wiki_collection, "db.wiki", Bson.opa2doc({_id=1; _rev=1}), 0)
-
-/**
- * Retrieves a json document from the database
- *
- * @param docid The id of the document to retrieve (arbitrary string)
- * @return A Template.content
- */
-get_content(docid) =
- default = Template.text("This page is empty. Double-click to edit.")
- extract_content(record:page) = record.content
- // Order by reverse _rev to get highest numbered _rev.
- orderby = {some=Bson.opa2doc({_rev=-1})}
- match MongoCollection.find_one(MongoCollection.orderby(wiki_collection,orderby),pageselect({_id=docid})) with
- | {success=page} ->
- source = extract_content(page)
- (match Template.try_parse(Template.default, source) with
- | {~success} -> success
- | {failure=_} -> Template.text(source))
- | {failure={NotFound}} ->
- default
- | {~failure} ->
- do jlog("hello_wiki_mongo: failure={MongoDriver.string_of_failure(failure)}")
- default
-
-/**
- * Read the content associated to a topic from the database and return the
- * corresponding source code.
- *
- * @param topic A topic (arbitrary string).
- * @return If a page has been saved in for [topic], the source code for this
- * page. Otherwise, the source code for the default page.
- */
-@publish load_source(topic) =
- Template.to_source(Template.default, get_content(topic))
-
-/**
- * Read the content associated to a topic from the database and return the
- * corresponding xhtml, ready to insert.
- *
- * @param topic A topic (arbitrary string).
- * @return If a page has been saved in for [topic], the xhtml for this
- * page. Otherwise, the xhtml for the default page.
- *
- * Note: This function does not perform any caching.
- */
-@publish load_rendered(topic) =
- Template.to_xhtml(Template.default, get_content(topic))
-
-/**
- * Accept source code, save the corresponding document in the database.
- *
- * @param topic A topic (arbitrary string).
- * @param source Source code to store at this topic. If this source code
- * is syntactically valid, store the template datastructure
- * corresponding to its content [Template.content].
- * Otherwise, the source code is implicitly replaced by the document
- * representing this raw code and this document is saved in the database.
- *
- * @return In case of success, the xhtml for the page that has just been
- * saved. In case of failure, an error message.
- */
-@publish save_source(topic, source) =
- select = pageselect({_id=topic})
- update = pageupdate({`$set`={content=source}; `$inc`={_rev=(1:Bson.int32)}})
- // Upsert this so we create it if it isn't there
- result = MongoCollection.updatee(MongoCollection.upsert(wiki_collection),select,update)
- if MongoDriver.is_error(result)
- then <>Error: {MongoDriver.pretty_of_result(result)}</>
- else
- match Template.try_parse(Template.default, source) with
- | ~{success} -> Template.to_xhtml(Template.default, success)
- | {failure = _} -> <>Error: {source}</>
-
-/**
- * {1 User interface}
- */
-
-/**
- * Set the user interface in edition mode.
- *
- * Load the source code for a topic, display an editable zone for this source code.
- *
- * @param topic The topic to edit.
- */
-edit(topic) =
- do Dom.set_value(#edit_content, load_source(topic))
- do Dom.hide(#show_content)
- do Dom.show(#edit_content)
- do Dom.give_focus(#edit_content)
- void
-
-/**
- * Set the user interface in reading mode.
- *
- * Save the source code for a topic (extracted from [#edit_content]),
- * display the rendered version.
- *
- * @param topic The topic to save.
- */
-save(topic) =
- content = save_source(topic, Dom.get_value(#edit_content))
- do Dom.transform([#show_content <- content])
- do Dom.hide(#edit_content)
- do Dom.show(#show_content)
- void
-
-/**
- * Main user interface
- *
- * @param topic The topic being consulted
- * @return A resource, ready to be passed to a dispatcher.
- */
-display(topic) =
- Resource.styled_page("About {topic}", ["/resources/css.css"],
- <div class="topbar"><div class="fill"><div class="container">
- <div id=#logo></div>
- </div></div></div>
- <div class="content container">
- <div class="page-header"><h1>About {topic}</></>
- <div class="well" id=#show_content ondblclick={_ -> edit(topic)}>
- {load_rendered(topic)}
- </>
- <textarea rows="30" id=#edit_content onblur={_ -> save(topic)}></>
- </div>
- )
-
-/**
- * {1 Main application}
- */
-
-/**
- * Dispatch requests to the user interface
- *
- * Note: The empty request is dispatched as if it were "Hello".
- */
-start =
- | {path = [] ... } ->
- display("Hello")
- | {~path ...} ->
- display(String.capitalize(String.to_lower(String.concat("::", path))))
-
-/**
- * Statically embed a bundle of resources
- */
-server = Server.of_bundle([@static_include_directory("resources")])
-
-/**
- * Launch the [start] dispatcher
- */
-server = Server.simple_dispatch(start)
View
142 doc/manual.src/hello_wiki/hello_wiki_simple.opa
@@ -1,142 +0,0 @@
-/**
- * {1 Import standard classes of bootstrap css}
- *
- * see http://twitter.github.com/bootstrap/
- */
-import stdlib.themes.bootstrap
-
-/**
- * {1 Import markdown syntax}
- */
-import stdlib.tools.markdown
-
-/**
- * {1 Database and database interaction}
- */
-
-/**
- * Contents of the wiki.
- *
- * Pages which do not exist have content "This page is empty".
- */
-database stringmap(string) /wiki
-database /wiki[_] = "This page is empty. Double-click to edit."
-
-/**
- * Read the content associated to a topic from the database and return the
- * corresponding Markdown source.
- *
- * @param topic A topic (arbitrary string).
- * @return If a page has been saved in for [topic], the source for this
- * page. Otherwise, the source for the default page.
- */
-function load_source(topic) {
- /wiki[topic];
-}
-
-/**
- * Read the content associated to a topic from the database and return the
- * corresponding xhtml, ready to insert.
- *
- * @param topic A topic (arbitrary string).
- * @return If a page has been saved in for [topic], the xhtml for this
- * page. Otherwise, the xhtml for the default page.
- *
- * Note: This function does not perform any caching.
- */
-function load_rendered(topic) {
- source = load_source(topic);
- Markdown.xhtml_of_string(Markdown.default_options, source);
-}
-
-/**
- * Accept source and save the corresponding document in the database.
- *
- * @param topic A topic (arbitrary string).
- * @param source Markdown source to store at this topic.
- * @return The xhtml for the page that has just been saved.
- */
-function save_source(topic, source) {
- /wiki[topic] <- source;
- load_rendered(topic);
-}
-
-/**
- * {1 User interface}
- */
-
-/**
- * Set the user interface in edition mode.
- *
- * Load the Markdown source for a topic, display an editable zone
- * for this markdown.
- *
- * @param topic The topic to edit.
- */
-function edit(topic) {
- Dom.set_value(#edit_content, load_source(topic));
- Dom.hide(#show_content);
- Dom.show(#edit_content);
- Dom.give_focus(#edit_content);
-}
-
-/**
- * Set the user interface in reading mode.
- *
- * Save the Markdown source for a topic (extracted from [#edit_content]),
- * display the rendered version.
- *
- * @param topic The topic to save.
- */
-function save(topic) {
- content = save_source(topic, Dom.get_value(#edit_content));
- #show_content = content;
- Dom.hide(#edit_content);
- Dom.show(#show_content);
-}
-
-/**
- * Main user interface
- *
- * @param topic The topic being consulted
- * @return A resource, ready to be passed to a dispatcher.
- */
-function display(topic) {
- Resource.styled_page("About {topic}", ["/resources/css.css"],
- <div class="topbar"><div class="fill"><div class="container"><div id=#logo></div></div></div></div>
- <div class="content container">
- <div class="page-header"><h1>About {topic}</></>
- <div class="well" id=#show_content ondblclick={function(_) { edit(topic) }}>{load_rendered(topic)}</>
- <textarea rows="30" id=#edit_content onblur={function(_) { save(topic) }}></>
- </div>
- );
-}
-
-/**
- * {1 Main application}
- */
-
-/**
- * Dispatch requests to the user interface
- *
- * Note: The empty request is dispatched as if it were "Hello".
- */
-function start(url) {
- match (url) {
- case { path : [], ... }: display("Hello");
- case ~{ path, ... }:
- display(String.capitalize(String.to_lower(String.concat("::", path))));
- }
-}
-
-/**
- * Start the wiki server
- */
-Server.start(
- Server.http,
- /** Statically embed a bundle of resources */
- [ {resources: @static_include_directory("resources")}
- /** Launch the [start] dispatcher */
- , {dispatch: start}
- ]
-);
View
13 doc/manual.src/hello_wiki/resources/css.css
@@ -1,13 +0,0 @@
-/***Header***/
-#logo {
- background: url("/resources/opa-logo.png") no-repeat scroll 0 0 transparent;
- height: 32px;
- margin: 10px 0 5px;
- width: 61px;
-}
-/***Editing area***/
-.content {margin-top:60px;}
-#edit_content {
- width:100%;
- display: none; /* initially hidden */
-}
View
BIN doc/manual.src/hello_wiki/resources/opa-logo.png
Deleted file not rendered
View
15 doc/manual.src/opa_binding_examples/.gitignore
@@ -1,15 +0,0 @@
-*.api
-*.api-txt
-*.log
-opa-debug-js
-*html
-_build
-*.opx
-*.opx.broken
-*.opp
-*.o
-*.dump
-*~
-.DS_Store
-_tracks
-*.exe
View
13 doc/manual.src/opa_binding_examples/Makefile
@@ -1,13 +0,0 @@
-all : plugin opa
-
-plugin:
- $(OPA_PLUGIN_BUILDER) -o plugin plugin.js plugin.ml
-
-opa:
- $(OPA) plugin.opp hello_bindings.opa
- @echo "run: ./hello_bindings.exe"
-
-clean:
- rm -rf hello_bindings.exe
- rm -rf _build _tracks
- rm -rf plugin.opp
View
10 doc/manual.src/opa_binding_examples/README.markdown
@@ -1,10 +0,0 @@
-Summary
--------
-
-This is a series of examples of binding Ocaml/C/JavaScript libraries in Opa.
-
-Compile with:
-
-`make`
-
-More about this example in Opa manual, chapter [Hello, bindings -- Binding other languages](http://doc.opalang.org/manual/Hello--bindings----Binding-other-languages).
View
18 doc/manual.src/opa_binding_examples/c_binding/Makefile
@@ -1,18 +0,0 @@
-DIR:=$(shell pwd)
-
-all: freq.o plugin opa
-
-freq.o: freq.c
- $(OCAMLOPT) freq.c
-
-plugin:
- $(OPA_PLUGIN_BUILDER) -o c_binding c_binding.ml
-
-opa:
- $(OPA) --mllopt $(DIR)/freq.o c_binding.opp freq.opa
- @echo "run: ./freq.exe"
-
-clean:
- rm -rf c_binding.opp
- rm -rf freq.exe freq.o
- rm -rf _build _tracks
View
2 doc/manual.src/opa_binding_examples/c_binding/c_binding.ml
@@ -1,2 +0,0 @@
-##register freq_get : -> int
-external freq_get : unit -> int = "freq_get"
View
54 doc/manual.src/opa_binding_examples/c_binding/freq.c
@@ -1,54 +0,0 @@
-#include <stdio.h>
-#include <sys/time.h>
-#include <string.h>
-#include <unistd.h>
-
-unsigned long long int rdtsc(void)
-{
- unsigned long long int x;
- __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
- return x;
-}
-
-int freq()
-{
- struct timezone tz;
- struct timeval tvstart, tvstop;
- unsigned long long int cycles[2];
- unsigned long microseconds;
- int mhz;
-
- memset(&tz, 0, sizeof(tz));
-
- gettimeofday(&tvstart, &tz);
- cycles[0] = rdtsc();
- gettimeofday(&tvstart, &tz);
-
- usleep(250000);
-
- gettimeofday(&tvstop, &tz);
- cycles[1] = rdtsc();
- gettimeofday(&tvstop, &tz);
-
- microseconds = ((tvstop.tv_sec-tvstart.tv_sec)*1000000) + (tvstop.tv_usec-tvstart.tv_usec);
-
- mhz = (int) (cycles[1]-cycles[0]) / microseconds;
-
- // printf("%i MHz\n",mhz);
-
- return mhz;
-}
-
-// OCAML binding
-#include <errno.h>
-#include <caml/mlvalues.h>
-#include <caml/memory.h>
-#include <caml/alloc.h>
-#include <caml/compatibility.h>
-#include <caml/fail.h>
-
-value freq_get()
-{
- CAMLparam0();
- CAMLreturn(Val_int(freq()));
-}
View
2 doc/manual.src/opa_binding_examples/c_binding/freq.opa
@@ -1,2 +0,0 @@
-freq_get = %%c_binding.freq_get%%
-print("freq : {freq_get()} Mhz\n");
View
10 doc/manual.src/opa_binding_examples/external_types/Makefile
@@ -1,10 +0,0 @@
-all : plugin opa
-
-plugin:
- $(OPA_PLUGIN_BUILDER) -o bigint bigint.ml
-
-opa:
- $(OPA) bigint.opp bigint.opa
-
-clean:
- rm -rf _build _tracks bigint.opp bigint.exe *.log
View
37 doc/manual.src/opa_binding_examples/external_types/bigint.ml
@@ -1,37 +0,0 @@
-(**
- Minimal Opa Binding for the Big_int module (Opa Manual)
-*)
-
-(**
- External type definition.
- The left part is the name of the type as it will be available in Opa.
- The right part is the name of the type as it is defined by the Ocaml library
-*)
-##extern-type BigInt.t = Big_int.big_int
-
-(**
- For this example, we will export a reduced API, just to add 2 big int
- given by the user of a very simple web page.
-*)
-
-(**
- This function exists already 'as is' in the Ocaml library,
- we can use the \ ` ` syntax : the function will be inlined in
- the generated code.
-*)
-##register add \ `Big_int.add_big_int` : BigInt.t, BigInt.t -> BigInt.t
-
-(**
- We prefer to deal with option for handling error cases in Opa.
-*)
-##register of_string : string -> option(BigInt.t)
-let of_string string =
- try
- Some (Big_int.big_int_of_string string)
- with
- | _ -> None
-
-(**
- And we want to see the result
-*)
-##register to_string \ `Big_int.string_of_big_int` : BigInt.t -> string
View
82 doc/manual.src/opa_binding_examples/external_types/bigint.opa
@@ -1,82 +0,0 @@
-/**
- * Simple server using big int
-**/
-
-/**
- * {1 Binding}
-**/
-
-/**
- * The type definition in opa.
- * The name should be the same as the one used in the plugin
- * The keywork 'external' means that the implementation is not
- * available in Opa, and values of this type can only be manipulated
- * via the API of the plugin.
-**/
-type BigInt.t = external
-
-module BigInt {
-
- /**
- * The syntax for binding foreign functions is %% key %%
- **/
- add = %% bigint.add %%
- to_string = %% bigint.to_string %%
-
- /**
- * For lisibility of the code, we can add types coercion
- **/
- (string -> option(BigInt.t)) of_string = %% bigint.of_string %%
-
-}
-
-/**
- * {1 Web page}
-**/
-
-/**
- * Compute the addition, or return a hint message in case of error
-**/
-exposed function compute(a, b) {
- match ((BigInt.of_string(a), BigInt.of_string(b))) {
- case ({some: i_a}, {some: i_b}):
- i_add = BigInt.add(i_a, i_b);
- BigInt.to_string(i_add);
- case ({ none }, _): "\"{a}\" is not a valid big int"
- default: "\"{b}\" is not a valid big int"
- }
-}
-
-/**
- * Action when the user will click on the 'add' button.
- * get the values of the 2 inputs, and store the result
- * in the result box
-**/
-function action() {
- a = Dom.get_value(#input_a);
- b = Dom.get_value(#input_b);
- #result = compute(a, b);
-}
-
-function button(string id, string message) {
- <a id={id}
- class="button"
- ref="#"
- onclick={function(_) {action()}}>{message}
- </a>
-}
-
-function page() {
- <>
- <h1>Big int Binding</h1>
- <h2>Arguments</h2>
- <input style="width:100%" id="input_a"/><br/>
- <input style="width:100%" id="input_b"/>
- <h2>Addition (on the server, using the external implementation)</h2>
- <div id="result" />
- <br/>
- {button("addition", "add")}<br/>
- </>
-}
-
-Server.start(Server.http, {title: "Bigint Binding", ~page});
View
41 doc/manual.src/opa_binding_examples/hello_bindings.opa
@@ -1,41 +0,0 @@
-plugin_stammer = %%plugin.stammer%%
-
-server stammer_server = plugin_stammer
-client stammer_client = plugin_stammer
-
-function stammer(a, side) {
- match (side) {
- case { on_client }: stammer_client(a);
- case { on_server }: stammer_server(a);
- }
-
-}
-
-function action(side) {
- a = Dom.get_value(#input_a);
- #result = stammer(a, side);
-}
-
-function button(string id, string message, side) {
- <a id={id}
- class="button"
- ref="#"
- onclick={function(_) { action(side) }}>{message}
- </a>
-}
-
-function page() {
- <>
- <h1>Hello Bindings</h1>
- <h2>Argument</h2>
- <input id="input_a"/>
- <h2>Result</h2>
- <div id="result" />
- <br/>
- <h2>Calling functions (using argument input)</h2>
- {button("stammer_client", "Compute stammer on the client", {on_client})}<br/>
- {button("stammer_server", "Compute stammer on the server", {on_server})}<br/>
- </>
-}
-
-Server.start(Server.http, {title: "Hello Bindings", ~page});
View
17 doc/manual.src/opa_binding_examples/opa_types/Makefile
@@ -1,17 +0,0 @@
-### if Opa has been compiled with Dbm support, nothing to add (comment these lines)
-### if Opa compiler is without Dbm support, uncomment them
-### dbm is in a subdirectory of ocaml libs
-INCLUDE=-I +dbm
-LINK=dbm.cmxa
-
-
-all : plugin opa
-
-plugin:
- $(OPA_PLUGIN_BUILDER) $(INCLUDE) -o dbm dbm.ml
-
-opa:
- $(OPA) $(INCLUDE) $(LINK) dbm.opp dbm.opa
-
-clean:
- rm -rf _build _tracks dbm.opp dbm.exe *.log
View
134 doc/manual.src/opa_binding_examples/opa_types/dbm.ml
@@ -1,134 +0,0 @@
-(**
- 1)
- Minimal Opa Binding for Dbm
-*)
-
-##extern-type dbm = Dbm.t
-
-(**
- Open a dbm database given its name.
- Return None in case of an error
-*)
-##register open_db : string -> option(dbm)
-let open_db name =
- let flags = [ Dbm.Dbm_rdwr ; Dbm.Dbm_create ] in
- let permission = 0o644 in
- try
- Some (Dbm.opendbm name flags permission)
- with
- | _ -> None
-
-(**
- Close the database
-*)
-##register close_db \ ` Dbm.close` : dbm -> void
-
-(**
- Find
- Option for opa
-*)
-##register find : dbm, string -> option(string)
-let find dbm key =
- try
- Some (Dbm.find dbm key)
- with
- | Not_found -> None
-
-(**
- Add or replace
-*)
-##register add \ `Dbm.replace` : dbm, string, string -> void
-
-(**
- 2)
- Specialization of the Dbm database
- for a tiny 3 fields database
-*)
-
-(**
- We will store in the database a list of people, indexed by their name
- The type [person] is defined in opa, and we will manipulate it there
- using an [opa-type] construction, with the [ServerLib]
-*)
-##opa-type person
-
-(**
- We will build a representation in Ocaml
-*)
-type person = {
- name : string ;
- age : int ;
- email : string ;
-}
-
-##extern-type ocaml_person = person
-
-(**
- Implementing a traduction between opa and ocaml structures
-*)
-
-(**
- We should define the field of the structure
-*)
-let field_name = ServerLib.static_field_of_name "name"
-let field_age = ServerLib.static_field_of_name "age"
-let field_email = ServerLib.static_field_of_name "email"
-
-(**
- From Ocaml to Opa
-*)
-##register opa_person_of_ocaml_person : ocaml_person -> opa[person]
-let opa_person_of_ocaml_person ocaml_person =
- let { name ; age ; email } = ocaml_person in
- let opa_person = List.fold_left
- (fun acc (field, value) ->
- ServerLib.add_field acc field value)
- ServerLib.empty_record_constructor
- [
- field_name, Obj.repr (ServerLib.wrap_string name) ;
- field_age, Obj.repr (ServerLib.wrap_int age) ;
- field_email, Obj.repr (ServerLib.wrap_string email) ;
- ]
- in
- wrap_opa_person (ServerLib.make_record opa_person)
-
-(**
- From Opa to Ocaml
-*)
-##register ocaml_person_of_opa_person : opa[person] -> ocaml_person
-let ocaml_person_of_opa_person opa_person =
- let record = unwrap_opa_person opa_person in
- let name = ServerLib.unsafe_dot record field_name in
- let age = ServerLib.unsafe_dot record field_age in
- let email = ServerLib.unsafe_dot record field_email in
- {
- name = ServerLib.unwrap_string name ;
- age = ServerLib.unwrap_int age ;
- email = ServerLib.unwrap_string email ;
- }
-
-(**
- Add a person in a database, printing some logs on the server side
- For the simplicity of this tutorial, we use a marshaling of the
- ocaml structure.
-*)
-##register add_person : dbm, opa[person] -> void
-let add_person dbm person =
- let ocaml_person = ocaml_person_of_opa_person person in
- Printf.eprintf "adding %S/%d/%S in the database\n%!"
- ocaml_person.name
- ocaml_person.age
- ocaml_person.email
- ;
- Dbm.replace dbm ocaml_person.name (Marshal.to_string ocaml_person [])
-
-(**
- Find a person in a database
-*)
-##register find_person : dbm, string -> option(opa[person])
-let find_person dbm name =
- match find dbm name with
- | None -> None
- | Some ocaml_person ->
- let ocaml_person = Marshal.from_string ocaml_person 0 in
- Some (opa_person_of_ocaml_person ocaml_person)
View
125 doc/manual.src/opa_binding_examples/opa_types/dbm.opa
@@ -1,125 +0,0 @@
-/**
- * Simple page using dbm
-**/
-
-import stdlib.system
-
-type dbm = external
-
-type person = {
- string name,
- int age,
- string email
-}
-
-/**
- * We open the database when the server is initializing,
- * and close it at the end of the execution, e.g. after a SIGINT
-**/
-dbm dbm =
- name = "people.dbm"
- dbm =
- match (%%dbm.open_db%%(name)) {
- case { some: dbm }: dbm
- case { none }: @fail("cannot open dbm database at {name}")
- }
- _ = System.at_exit(function () { %%dbm.close_db%%(dbm) })
- dbm
-
-
-/**
- * Client interface to the Db
-**/
-exposed
-function find_person(name) {
- %%dbm.find_person%%(dbm, name);
-}
-
-exposed
-function add_person(person) {
- // Because this function is exposed, it should check that person is well formed.
- // e.g. name is not too long ...
- %%dbm.add_person%%(dbm, person);
-}
-
-
-
-/**
- * Find an entry in the ndbm from the contains of the Name box
-**/
-function action_find() {
- Dom.clear_value(#age);
- Dom.clear_value(#email);
- name = Dom.get_value(#name)
- match (find_person(name)) {
- case { some: person }:
- Dom.set_value(#age, string_of_int(person.age));
- Dom.set_value(#email, person.email);
- void
- case { none }:
- result("\"{name}\" Not-found")
- }
-}
-
-function result(string) {
- #result = string
-}
-
-/**
- * Submit the truplet in the ndbm
-**/
-function action_submit() {
- name = Dom.get_value(#name)
- age = Parser.int(Dom.get_value(#age)) ? 0
- email = Dom.get_value(#email)
- person = ~{ name, age, email }
- add_person(person);
- Dom.clear_value(#name);
- Dom.clear_value(#age);
- Dom.clear_value(#email);
- result("Done");
- void
-}
-
-/**
- * Guess the age of the captain
-**/
-
-the_captain = "The Captain"
-the_question = "What is the age of \"{the_captain}\" ?"
-
-function action_captain() {
- match (find_person(the_captain)) {
- case { some: person }:
- result("The captain is {person.age} years old")
- case { none }:
- result("I don't know")
- }
-}
-
-function page() {
- <>
- <h1>Dbm Binding</h1>
- <h2>New entry</h2>
- <table border="1">
- <tr>
- <th>Name</th>
- <th>Age</th>
- <th>Email</th>
- </tr>
- <tr>
- <td><input id="name"/></td>
- <td><input id="age"/></td>
- <td><input id="email"/></td>
- </tr>
- </table>
- <a class="button" ref="#" onclick={function (_) { action_find() }}>Find</a>
- <a class="button" ref="#" onclick={function (_) { action_submit() }}>Submit</a>
- <br/>
- <a class="button" ref="#" onclick={function (_) { action_captain() }}>{the_question}</a>
- <br/>
- <div id="result" />
- </>
-}
-
-Server.start(Server.http, {title: "Dbm Binding", ~page})
View
9 doc/manual.src/opa_binding_examples/plugin.js
@@ -1,9 +0,0 @@
-// This is a JavaScript file, containing opa preprocessing directives
-
-##register stammer : string -> string
-##args(s)
-{
- // this is a standard javascript code,
- // we are there in the body of a function, with an argument named 's'
- return "client is stammering: " + s + s + s ;
-}
View
4 doc/manual.src/opa_binding_examples/plugin.ml
@@ -1,4 +0,0 @@
-(* This is an Ocaml file, containing opa preprocessing directives *)
-
-##register stammer : string -> string
-let stammer s = "server is stammering: " ^ s ^ s ^ s
1 doc/manual.src/opa_bindings_examples