nit.git
7 years agoNOTICE: Update author list and years
Jean-Christophe Beaupré [Mon, 23 May 2016 23:36:37 +0000 (19:36 -0400)]
NOTICE: Update author list and years

Signed-off-by: Jean-Christophe Beaupré <jcbrinfo@users.noreply.github.com>

7 years agoMerge: Refactorize nitunit
Jean Privat [Sun, 22 May 2016 12:56:17 +0000 (08:56 -0400)]
Merge: Refactorize nitunit

Future improvement of nitunit require a saner codebase.
This PR does not bring a lot of features but propose instead some code improvements.

Summary:

* a new class UnitTest to factorize DocUnit and TestCase
* DocUnit are created, with its metadata, while discovered
* DocUnit do not enclose a XML node to fill but will generate one with to_xml.
* Easter egg: precise locations are included in the DocUnits. Each line of *collected* code can be located back to the original source code. This feature is not really used yet, except to locate the docunit itself.

The last commits are divided in order to make the reviewing more easy. I tought that is was better than a big stashed change.

Future PR will target usability since unit-tests are now reified in a common way on both sides (docunits and testsuites).

Pull-Request: #2114
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>

7 years agoMerge: Document Docker
Jean Privat [Sat, 21 May 2016 05:40:50 +0000 (01:40 -0400)]
Merge: Document Docker

Add documentation and an example of a docker image for a Nit application

Pull-Request: #2116
Reviewed-by: Alexis Laferrière <alexis.laf@xymus.net>
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>

7 years agoMerge: gamnit: miscellaneous services and a few fixes
Jean Privat [Sat, 21 May 2016 05:40:41 +0000 (01:40 -0400)]
Merge: gamnit: miscellaneous services and a few fixes

This PR groups features required by my recent unpublished tech demos built on gamnit.

Here are more details on the less intuitive commits:

* The change to `current_fps` lets a program use it right from the beginning and gives a value which is somewhat realistic (vs returning 0).
* The `placeholder_model` can be useful when quickly writing the prototype of a game to get something visible in the 3D space.
* The doc of `subtexture` clarifies an ambiguity as to whether the method expected pixel offsets or proportional values out of 1.0.
* The tool `texture_atlas_parser` can be useful to other games.
* `draw_mode` is very useful to create optimized `Mesh`, using `gl_TRIANGLE_STRIP` and `gl_TRIANGLE_FAN`.
* The old API of `triangulate` was counter-intuitive. The result was put in a parameter and the list of points was cleared in the process. This PR offers a simple method and the recursive implementation as an optimized alternative. ping @BlackMinou
* `tinks_vr` is not playable but it shows how to convert a gamnit game to a basic VR version.

Pull-Request: #2115
Reviewed-by: Jean Privat <jean@pryen.org>

7 years agoMerge: src/platforms: fallback to version field "0" on error when asking for a git_re...
Jean Privat [Sat, 21 May 2016 05:40:13 +0000 (01:40 -0400)]
Merge: src/platforms: fallback to version field "0" on error when asking for a git_revision

The _app.nit_ annotation `version` sets the version of mobile app packages (.apk and .app). For example, `version(1, 5, git_revision)` may produce the version string "1.5.6b42a7c".

This PR fixes an error when asking for a `git_revision` but the call to `git rev-parse` fails.
Note that the normal git error is printed before the nitc warning message, so debugging should be easy.

Close #2111

Pull-Request: #2113
Reviewed-by: Jean Privat <jean@pryen.org>

7 years agoMerge: Nitweb uses popcorn
Jean Privat [Sat, 21 May 2016 05:40:11 +0000 (01:40 -0400)]
Merge: Nitweb uses popcorn

Get rid of plain corn boiler plate code from nitweb.

Consider only the last two commits since the others are from #2094 and #2110.

Pull-Request: #2112
Reviewed-by: Jean Privat <jean@pryen.org>

7 years agodocker: add a README
Jean Privat [Sat, 21 May 2016 05:39:19 +0000 (01:39 -0400)]
docker: add a README

Signed-off-by: Jean Privat <jean@pryen.org>

7 years agodocker: add a Dockerfile example
Jean Privat [Sat, 21 May 2016 05:38:59 +0000 (01:38 -0400)]
docker: add a Dockerfile example

Signed-off-by: Jean Privat <jean@pryen.org>

7 years agoFix PATH and WORKDIR with Docker images
Jean Privat [Sat, 21 May 2016 05:37:17 +0000 (01:37 -0400)]
Fix PATH and WORKDIR with Docker images

Signed-off-by: Jean Privat <jean@pryen.org>

7 years agotests: update sav for nitunit
Jean Privat [Sat, 21 May 2016 05:35:17 +0000 (01:35 -0400)]
tests: update sav for nitunit

Signed-off-by: Jean Privat <jean@pryen.org>

7 years agonitunit/docunit: consider invalid-block as prefailed nitunits
Jean Privat [Fri, 20 May 2016 18:51:15 +0000 (14:51 -0400)]
nitunit/docunit: consider invalid-block as prefailed nitunits

Signed-off-by: Jean Privat <jean@pryen.org>

7 years agonitunit: remove old tc object used for names
Jean Privat [Fri, 20 May 2016 18:50:09 +0000 (14:50 -0400)]
nitunit: remove old tc object used for names

Signed-off-by: Jean Privat <jean@pryen.org>

7 years agonitunit: DocUnit is also a TestUnit
Jean Privat [Fri, 20 May 2016 18:45:54 +0000 (14:45 -0400)]
nitunit: DocUnit is also a TestUnit

Signed-off-by: Jean Privat <jean@pryen.org>

7 years agosrc/web: nitweb use popcorn
Alexandre Terrasa [Fri, 20 May 2016 00:01:31 +0000 (20:01 -0400)]
src/web: nitweb use popcorn

Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

7 years agosrc/web: render do not require the server reference anymore
Alexandre Terrasa [Thu, 19 May 2016 23:46:56 +0000 (19:46 -0400)]
src/web: render do not require the server reference anymore

Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

7 years agocontrib/tinks: add VR
Alexis Laferrière [Mon, 18 Jan 2016 04:59:35 +0000 (23:59 -0500)]
contrib/tinks: add VR

Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

7 years agolib/geometry: change triangulate API for easier usage
Alexis Laferrière [Tue, 23 Feb 2016 17:24:47 +0000 (12:24 -0500)]
lib/geometry: change triangulate API for easier usage

The old API was counter intuitive. The result was put in a parameter and
the list of points was cleared in the process.

Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

7 years agolib/gamnit: intro draw_mode
Alexis Laferrière [Wed, 10 Feb 2016 02:37:56 +0000 (21:37 -0500)]
lib/gamnit: intro draw_mode

This is very useful to create optimized Mesh, using gl_TRIANGLE_STRIP and gl_TRIANGLE_FAN.

Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

7 years agolib/gamnit & egl: extract number of color bits as attributes
Alexis Laferrière [Fri, 20 May 2016 18:35:51 +0000 (14:35 -0400)]
lib/gamnit & egl: extract number of color bits as attributes

Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

7 years agolib/gamnit: fix order on the color bits count
Alexis Laferrière [Sun, 7 Feb 2016 18:37:55 +0000 (13:37 -0500)]
lib/gamnit: fix order on the color bits count

Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

7 years agolib/gamnit: rename GamnitAssetTexture to TextureAsset
Alexis Laferrière [Sun, 7 Feb 2016 17:22:58 +0000 (12:22 -0500)]
lib/gamnit: rename GamnitAssetTexture to TextureAsset

Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

7 years agolib/gamnit: fix wrap of subtextures on models
Alexis Laferrière [Sun, 7 Feb 2016 17:22:13 +0000 (12:22 -0500)]
lib/gamnit: fix wrap of subtextures on models

Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

7 years agolib/gamnit: move texture_atlas_parser
Alexis Laferrière [Sat, 6 Feb 2016 23:53:32 +0000 (18:53 -0500)]
lib/gamnit: move texture_atlas_parser

This tool can be useful to other games.

Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

7 years agolib/gamnit: intro GamnitProgram::diagnose
Alexis Laferrière [Sat, 6 Feb 2016 23:48:11 +0000 (18:48 -0500)]
lib/gamnit: intro GamnitProgram::diagnose

Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

7 years agolib/gamnit: fix `cube::tex_coords`
Alexis Laferrière [Thu, 21 Jan 2016 16:27:50 +0000 (11:27 -0500)]
lib/gamnit: fix `cube::tex_coords`

Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

7 years agolib/gamnit: improve doc of subtexture with a vital detail
Alexis Laferrière [Wed, 20 Apr 2016 11:33:47 +0000 (07:33 -0400)]
lib/gamnit: improve doc of subtexture with a vital detail

There was an ambiguity as to whether the method expected pixel offsets original
proportional values out of 1.0.

Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

7 years agolib/gamnit: extract placeholder model
Alexis Laferrière [Sat, 16 Apr 2016 16:06:19 +0000 (12:06 -0400)]
lib/gamnit: extract placeholder model

This model can be useful when quickly writing the prototype of a game
to get something visible in the 3D space.

Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

7 years agolib/gamnit: initialize `current_fps` to `maximum_fps`
Alexis Laferrière [Sat, 16 Apr 2016 16:06:07 +0000 (12:06 -0400)]
lib/gamnit: initialize `current_fps` to `maximum_fps`

This lets a program use `current_fps` right from the beginning and
gives a value which is somewhat realistic (vs returning 0).

Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

7 years agonitunit: new class UnitTest to factorize TestCase and DocUnit
Jean Privat [Fri, 20 May 2016 18:41:52 +0000 (14:41 -0400)]
nitunit: new class UnitTest to factorize TestCase and DocUnit

Signed-off-by: Jean Privat <jean@pryen.org>

7 years agonitunit: docunit have their own location
Jean Privat [Fri, 20 May 2016 17:26:35 +0000 (13:26 -0400)]
nitunit: docunit have their own location

Signed-off-by: Jean Privat <jean@pryen.org>

7 years agonitunit: docunits are directly created while discovering.
Jean Privat [Fri, 20 May 2016 17:24:11 +0000 (13:24 -0400)]
nitunit: docunits are directly created while discovering.

No need to create then latter.

Signed-off-by: Jean Privat <jean@pryen.org>

7 years agosrc/platforms: fallback to "0" on error when asking for a git_revision
Alexis Laferrière [Fri, 20 May 2016 14:40:42 +0000 (10:40 -0400)]
src/platforms: fallback to "0" on error when asking for a git_revision

Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

7 years agoMerge: Update nitweb
Jean Privat [Fri, 20 May 2016 02:29:50 +0000 (22:29 -0400)]
Merge: Update nitweb

Update nitweb to use #2024 and #2041.

Pull-Request: #2110
Reviewed-by: Jean Privat <jean@pryen.org>

7 years agoMerge: Split and improve Docker
Jean Privat [Fri, 20 May 2016 02:29:46 +0000 (22:29 -0400)]
Merge: Split and improve Docker

I splitted the image in a light and a full one: https://hub.docker.com/r/privat/mynit/tags/

* the light one contains only the nit tools the the packages to build them. 225MB
* the full one contains most libraries, tools like inkscape, and the android sdk. 2GB

Pull-Request: #2109
Reviewed-by: Alexis Laferrière <alexis.laf@xymus.net>

7 years agoMerge: nitcatalog: count warnings per 1000 lines of code (w/kloc)
Jean Privat [Fri, 20 May 2016 02:29:41 +0000 (22:29 -0400)]
Merge: nitcatalog: count warnings per 1000 lines of code (w/kloc)

The raw number of warnings is not that useful.
Number of warnings per 1000 lines of code make it more semantic.

Signed-off-by: Jean Privat <jean@pryen.org>

Pull-Request: #2108
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>

7 years agoMerge: Popcorn
Jean Privat [Fri, 20 May 2016 02:29:34 +0000 (22:29 -0400)]
Merge: Popcorn

# Popcorn

**Why endure plain corn when you can pop it?!**

Popcorn is a minimal yet powerful nit web application framework that provides cool
features for lazy developpers.

Popcorn is built over nitcorn to provide a clean and user friendly interface
without all the boiler plate code.

## What does it taste like?

Set up is quick and easy as 10 lines of code.
Create a file `app.nit` and add the following code:

~~~nit
import popcorn

class HelloHandler
super Handler

redef fun get(req, res) do res.html "<h1>Hello World!</h1>"
end

var app = new App
app.use("/", new HelloHandler)
# app.listen("localhost", 3000)
~~~

The Popcorn app listens on port 3000 for connections.
The app responds with "Hello World!" for requests to the root URL (`/`) or **route**.
For every other path, it will respond with a **404 Not Found**.

The `req` (request) and `res` (response) parameters are the same that nitcorn provides
so you can do anything else you would do in your route without Popcorn involved.

Run the app with the following command:

~~~bash
nitc app.nit && ./app
~~~

Then, load [http://localhost:3000](http://localhost:3000) in a browser to see the output.

This is why we love popcorn!

## Basic routing

**Routing** refers to determining how an application responds to a client request
to a particular endpoint, which is a URI (or path) and a specific HTTP request
method GET, POST, PUT or DELETE (other methods are not suported yet).

Each route can have one or more handler methods, which are executed when the route is matched.

Route handlers definition takes the following form:

~~~nit
import popcorn

class MyHandler
super Handler

redef fun METHOD(req, res) do end
end
~~~

Where:
* `MyHandler` is the name of the handler you will add to the app.
* `METHOD` can be replaced by `get`, `post`, `put` or `delete`.

The following example responds with `Hello World!` to GET and POST requests:

~~~nit
import popcorn

class MyHandler
super Handler

redef fun get(req, res) do res.send "Got a GET request"
redef fun post(req, res) do res.send "Got a POST request"
end
~~~

To make your handler responds to a specific route, you have to add it to the app.

Respond to POST request on the root route (`/`), the application's home page:

~~~nit
var app = new App
app.use("/", new MyHandler)
~~~

Respond to a request to the `/user` route:

~~~nit
app.use("/user", new MyHandler)
~~~

For more details about routing, see the routing section.

## Serving static files with Popcorn

To serve static files such as images, CSS files, and JavaScript files, use the
Popcorn built-in handler `StaticHandler`.

Pass the name of the directory that contains the static assets to the StaticHandler
init method to start serving the files directly.
For example, use the following code to serve images, CSS files, and JavaScript files
in a directory named `public`:

~~~nit
app.use("/", new StaticHandler("public/"))
~~~

Now, you can load the files that are in the `public` directory:

~~~raw
http://localhost:3000/images/trollface.jpg
http://localhost:3000/css/style.css
http://localhost:3000/js/app.js
http://localhost:3000/hello.html
~~~

Popcorn looks up the files relative to the static directory, so the name of the
static directory is not part of the URL.
To use multiple static assets directories, add the `StaticHandler` multiple times:

~~~nit
app.use("/", new StaticHandler("public/"))
app.use("/", new StaticHandler("files/"))
~~~

Popcorn looks up the files in the order in which you set the static directories
with the `use` method.

To create a virtual path prefix (where the path does not actually exist in the file system)
for files that are served by the `StaticHandler`, specify a mount path for the
static directory, as shown below:

~~~nit
app.use("/static/", new StaticHandler("public/"))
~~~

Now, you can load the files that are in the public directory from the `/static`
path prefix.

~~~raw
http://localhost:3000/static/images/trollface.jpg
http://localhost:3000/static/css/style.css
http://localhost:3000/static/js/app.js
http://localhost:3000/static/hello.html
~~~

However, the path that you provide to the `StaticHandler` is relative to the
directory from where you launch your app.
If you run the app from another directory, it’s safer to use the absolute path of
the directory that you want to serve.

## Advanced Routing

**Routing** refers to the definition of application end points (URIs) and how
they respond to client requests. For an introduction to routing, see the Basic routing
section.

The following code is an example of a very basic route.

~~~nit
import popcorn

class HelloHandler
super Handler

redef fun get(req, res) do res.send "Hello World!"
end

var app = new App
app.use("/", new HelloHandler)
~~~

### Route methods

A **route method** is derived from one of the HTTP methods, and is attached to an
instance of the Handler class.

The following code is an example of routes that are defined for the GET and the POST
methods to the root of the app.

~~~nit
import popcorn

class GetPostHandler
super Handler

redef fun get(req, res) do res.send "GET request to the homepage"
redef fun post(req, res) do res.send "POST request to the homepage"
end

var app = new App
app.use("/", new GetPostHandler)
~~~

Popcorn supports the following routing methods that correspond to HTTP methods:
get, post, put, and delete.

The request query string is accessed through the `req` parameter:

~~~nit
import popcorn
import template

class QueryStringHandler
super Handler

redef fun get(req, res) do
var tpl = new Template
tpl.addn "URI: {req.uri}"
tpl.addn "Query string: {req.query_string}"
for name, arg in req.get_args do
tpl.addn "{name}: {arg}"
end
        res.send tpl
end
end

var app = new App
app.use("/", new QueryStringHandler)
# app.listen("localhost", 3000)
~~~

Post parameters can also be accessed through the `req` parameter:

~~~nit
import popcorn
import template

class PostHandler
super Handler

redef fun post(req, res) do
var tpl = new Template
tpl.addn "URI: {req.uri}"
tpl.addn "Body: {req.body}"
for name, arg in req.post_args do
tpl.addn "{name}: {arg}"
end
        res.send tpl
end
end

var app = new App
app.use("/", new PostHandler)
# app.listen("localhost", 3000)
~~~

There is a special routing method, `all(res, req)`, which is not derived from any
HTTP method. This method is used to respond at a path for all request methods.

In the following example, the handler will be executed for requests to "/user"
whether you are using GET, POST, PUT, DELETE, or any other HTTP request method.

~~~nit
import popcorn

class AllHandler
super Handler

redef fun all(req, res) do res.send "Every request to the homepage"
end
~~~

Using the `all` method you can also implement other HTTP request methods.

~~~nit
import popcorn

class MergeHandler
super Handler

redef fun all(req, res) do
if req.method == "MERGE" then
# handle that method
else super # keep handle GET, POST, PUT and DELETE methods
end
end
~~~

### Route paths

**Route paths**, in combination with a request handlers, define the endpoints at
which requests can be made.
Route paths can be strings, parameterized strings or glob patterns.
Query strings such as `?q=foo`are not part of the route path.

Popcorn uses the `Handler::match(uri)` method to match the route paths.

Here are some examples of route paths based on strings.

This route path will match requests to the root route, `/`.

~~~nit
import popcorn

class MyHandler
super Handler

redef fun get(req, res) do res.send "Got a GET request"
end

var app = new App
app.use("/", new MyHandler)
~~~

This route path will match requests to `/about`.

~~~nit
app.use("/about", new MyHandler)
~~~

This route path will match requests to `/random.text`.

~~~nit
app.use("/random.text", new MyHandler)
~~~

During the query/response process, routes are matched by order of declaration
through the `App::use` method.

The app declared in this example will try to match the routes in this order:

1. `/`
2. `/about`
3. `/random.text`

### Route parameters

**Route parameters** are variable parts of a route path. They can be used to path
arguments within the URI.\13
Parameters in a route are prefixed with a colon `:` like in `:userId`, `:year`.

The following example declares a handler `UserHome` that responds with the `user`
name.

~~~nit
import popcorn

class UserHome
super Handler

redef fun get(req, res) do
var user = req.param("user")
if user != null then
res.send "Hello {user}"
else
res.send("Nothing received", 400)
end
end
end

var app = new App
app.use("/:user", new UserHome)
# app.listen("localhost", 3000)
~~~

The `UserHome` handler listen to every path matching `/:user`. This can be `/Morriar`,
`/10`, ... but not `/Morriar/profile` since route follow the strict matching rule.

### Glob routes

**Glob routes** are routes that match only on a prefix, thus accepting a wider range
of URI.
Glob routes end with the symbol `*`.

Here we define a `UserItem` handler that will respond to any URI matching the prefix
`/user/:user/item/:item`.
Note that glob route are compatible with route parameters.

~~~nit
import popcorn

class UserItem
super Handler

redef fun get(req, res) do
var user = req.param("user")
var item = req.param("item")
if user == null or item == null then
res.send("Nothing received", 400)
else
res.send "Here the item {item} of the use {user}."
end
end
end

var app = new App
app.use("/user/:user/item/:item/*", new UserItem)
# app.listen("localhost", 3000)
~~~

## Response methods

The methods on the response object (`res`), can is used to manipulate the
request-response cycle.
If none of these methods are called from a route handler, the client request will
receive a `404 Not found` error.

* `res.html()` Send a HTML response.
* `res.json()` Send a JSON response.
* `res.redirect()` Redirect a request.
* `res.send()` Send a response of various types.
* `res.error()` Set the response status code and send its message as the response body.

## Middlewares

### Overview

**Middleware** handlers are handlers that typically do not send `HttpResponse` responses.
Middleware handlers can perform the following tasks:

* Execute any code.
* Make changes to the request and the response objects.
* End its action and pass to the next handler in the stack.

If a middleware handler makes a call to `res.send()`, it provoques the end the
request-response cycle and the response is sent to the client.

### Ultra simple logger example

Here is an example of a simple “Hello World” Popcorn application.
We add a middleware handler to the application called MyLogger that prints a simple
log message in the app stdout.

~~~nit
import popcorn

class MyLogger
super Handler

redef fun all(req, res) do print "Request Logged!"
end

class HelloHandler
super Handler

redef fun get(req, res) do res.send "Hello World!"
end

var app = new App
app.use("/*", new MyLogger)
app.use("/", new HelloHandler)
# app.listen("localhost", 3000)
~~~

By using the `MyLogger` handler to the route `/*` we ensure that every requests
(even 404 ones) pass through the middleware handler.
This handler just prints “Request Logged!” when a request is received.

The order of middleware loading is important: middleware functions that are loaded first are also executed first.
In the above example, `MyLogger` will be executed before `HelloHandler`.

### Ultra cool, more advanced logger example

Next, we’ll create a middleware handler called “LogHandler” that prints the requested
uri, the response status and the time it took to Popcorn to process the request.

~~~nit
import popcorn
import realtime

redef class HttpRequest
# Time that request was received by the Popcorn app.
var timer: nullable Clock = null
end

class RequestTimeHandler
super Handler

redef fun all(req, res) do req.timer = new Clock
end

class LogHandler
super Handler

redef fun all(req, res) do
var timer = req.timer
if timer != null then
print "{req.method} {req.uri} {res.color_status} ({timer.total})"
else
print "{req.method} {req.uri} {res.color_status}"
end
end
end

class HelloHandler
super Handler

redef fun get(req, res) do res.send "Hello World!"
end

var app = new App
app.use("/*", new RequestTimeHandler)
app.use("/", new HelloHandler)
app.use("/*", new LogHandler)
# app.listen("localhost", 3000)
~~~

First, we attach a new attribute `timer` to every `HttpRequest`.
Doing so we can access our data from all handlers that import our module, directly
from the `req` parameter.

We use the new middleware called `RequestTimeHandler` to initialize the request timer.

Finally, our `LogHandler` will display a bunch of data and use the request `timer`
to display the time it took to process the request.

The app now uses the `RequestTimeHandler` middleware for every requests received
by the Popcorn app.
The page is processed the `HelloHandler` to display the index page.
And, before every response is sent, the `LogHandler` is activated to display the
log line.

Because you have access to the request object, the response object, and all the
Popcorn API, the possibilities with middleware functions are endless.

### Built-in middlewares

Starting with version 0.1, Popcorn provide a set of built-in middleware that can
be used to develop your app faster.

* `RequestClock`: initializes requests clock.
* `ConsoleLog`: displays resquest and response status in console (can be used with `RequestClock`).
* `SessionInit`: initializes requests session (see the `Sessions` section).
* `StaticServer`: serves static files (see the `Serving static files with Popcorn` section).
* `Router`: a mountable mini-app (see the `Mountable routers` section).

## Mountable routers

Use the `Router` class to create modular, mountable route handlers.
A Router instance is a complete middleware and routing system; for this reason,
it is often referred to as a “mini-app”.

The following example creates a router as a module, loads a middleware handler in it,
defines some routes, and mounts the router module on a path in the main app.

~~~nit
import popcorn

class AppHome
super Handler

redef fun get(req, res) do res.send "Site Home"
end

class UserLogger
super Handler

redef fun all(req, res) do print "User logged"
end

class UserHome
super Handler

redef fun get(req, res) do res.send "User Home"
end

class UserProfile
super Handler

redef fun get(req, res) do res.send "User Profile"
end

var user_router = new Router
user_router.use("/*", new UserLogger)
user_router.use("/", new UserHome)
user_router.use("/profile", new UserProfile)

var app = new App
app.use("/", new AppHome)
app.use("/user", user_router)
# app.listen("localhost", 3000)
~~~

The app will now be able to handle requests to /user and /user/profile, as well
as call the `Time` middleware handler that is specific to the route.

## Error handling

**Error handling** is based on middleware handlers.

Define error-handling middlewares in the same way as other middleware handlers:

~~~nit
import popcorn

class SimpleErrorHandler
super Handler

redef fun all(req, res) do
if res.status_code != 200 then
print "An error occurred! {res.status_code})"
end
end
end

class HelloHandler
super Handler

redef fun get(req, res) do res.send "Hello World!"
end

var app = new App
app.use("/", new HelloHandler)
app.use("/*", new SimpleErrorHandler)
# app.listen("localhost", 3000)
~~~

In this example, every non-200 response is caught by the `SimpleErrorHandler`
that print an error in stdout.

By defining multiple middleware error handlers, you can take multiple action depending
on the kind of error or the kind of interface you provide (HTML, XML, JSON...).

Here an example of the 404 custom error page in HTML:

~~~nit
import popcorn
import template

class HtmlErrorTemplate
super Template

var status: Int
var message: nullable String

redef fun rendering do add """
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>{{{message or else status}}}</title>
</head>
<body>
<h1>{{{status}}} {{{message or else ""}}}</h1>
</body>
</html>"""
end

class HtmlErrorHandler
super Handler

redef fun all(req, res) do
if res.status_code != 200 then
res.send(new HtmlErrorTemplate(res.status_code, "An error occurred!"))
end
end
end

var app = new App
app.use("/*", new HtmlErrorHandler)
# app.listen("localhost", 3000)
~~~

## Sessions

**Sessions** can be used thanks to the built-in `SessionMiddleware`.

Here a simple example of login button that define a value in the `req` session.

~~~nit
import popcorn

redef class Session
var is_logged = false
end

class AppLogin
super Handler

redef fun get(req, res) do
res.html """
<p>Is logged: {{{req.session.as(not null).is_logged}}}</p>
<form action="/" method="POST">
<input type="submit" value="Login" />
</form>"""
end

redef fun post(req, res) do
req.session.as(not null).is_logged = true
res.redirect("/")
end
end

var app = new App
app.use("/*", new SessionInit)
app.use("/", new AppLogin)
# app.listen("localhost", 3000)
~~~

Notice the use of the `SessionInit` on the `/*` route. You must use the
`SessionInit` first to initialize the request session.
Without that, your request session will be set to `null`.
If you don't use sessions in your app, you do not need to include that middleware.

## Database integration

### Mongo DB

If you want to persist your data, Popcorn works well with MongoDB.

In this example, we will show how to store and list user with a Mongo database.

First let's define a handler that access the database to list all the user.
The mongo database reference is passed to the UserList handler through the `db` attribute.

Then we define a handler that displays the user creation form on GET requests.
POST requests are used to save the user data.

~~~nit
import popcorn
import mongodb
import template

class UserList
super Handler

var db: MongoDb

redef fun get(req, res) do
var users = db.collection("users").find_all(new JsonObject)

var tpl = new Template
tpl.add "<h1>Users</h1>"
tpl.add "<table>"
for user in users do
tpl.add """<tr>
<td>{{{user["login"] or else "null"}}}</td>
<td>{{{user["password"] or else "null"}}}</td>
</tr>"""
end
tpl.add "</table>"
res.html tpl
end
end

class UserForm
super Handler

var db: MongoDb

redef fun get(req, res) do
var tpl = new Template
tpl.add """<h1>Add a new user</h1>
<form action="/new" method="POST">
<input type="text" name="login" />
<input type="password" name="password" />
<input type="submit" value="save" />
</form>"""
res.html tpl
end

redef fun post(req, res) do
var json = new JsonObject
json["login"] = req.post_args["login"]
json["password"] = req.post_args["password"]
db.collection("users").insert(json)
res.redirect "/"
end
end

var mongo = new MongoClient("mongodb://localhost:27017/")
var db = mongo.database("mongo_example")

var app = new App
app.use("/", new UserList(db))
app.use("/new", new UserForm(db))
# app.listen("localhost", 3000)
~~~

## Angular.JS integration

Loving [AngularJS](https://angularjs.org/)? Popcorn is made for Angular and for you!

Using the StaticHandler with a glob route, you can easily redirect all HTTP requests
to your angular controller:

~~~nit
import popcorn

var app = new App
app.use("/*", new StaticHandler("my-ng-app/"))
# app.listen("localhost", 3000)
~~~

See the examples for a more detailed use case working with a JSON API.

Pull-Request: #2094
Reviewed-by: Istvan SZALAÏ <istvan.szalai@savoirfairelinux.com>
Reviewed-by: Jean Privat <jean@pryen.org>
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>

7 years agosrc/web: replace adhoc MEntity::to_json by the model_json one
Alexandre Terrasa [Thu, 19 May 2016 23:36:21 +0000 (19:36 -0400)]
src/web: replace adhoc MEntity::to_json by the model_json one

Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

7 years agosrc/web: actions use full_name to lookup mentities
Alexandre Terrasa [Thu, 19 May 2016 23:34:27 +0000 (19:34 -0400)]
src/web: actions use full_name to lookup mentities

Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

7 years agosrc/web: use full_name instead of html_raw_namespace
Alexandre Terrasa [Thu, 19 May 2016 23:33:54 +0000 (19:33 -0400)]
src/web: use full_name instead of html_raw_namespace

Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

7 years agosrc/web: ModelAction can search mentities by full_name
Alexandre Terrasa [Thu, 19 May 2016 23:32:51 +0000 (19:32 -0400)]
src/web: ModelAction can search mentities by full_name

Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

7 years agotests: do not try to test examples form lib/popcorn
Alexandre Terrasa [Fri, 20 May 2016 00:04:40 +0000 (20:04 -0400)]
tests: do not try to test examples form lib/popcorn

Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

7 years agolib/popcorn: create package
Alexandre Terrasa [Mon, 16 May 2016 19:05:34 +0000 (15:05 -0400)]
lib/popcorn: create package

Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

7 years agomodel/model_views: search mentity by full_name
Alexandre Terrasa [Thu, 19 May 2016 23:32:13 +0000 (19:32 -0400)]
model/model_views: search mentity by full_name

Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

7 years agonitcatalog: count warnings per 1000 lines of code (w/kloc)
Jean Privat [Thu, 19 May 2016 23:18:34 +0000 (19:18 -0400)]
nitcatalog: count warnings per 1000 lines of code (w/kloc)

The raw number of warnings is not that useful.
This metric make it more semantic.

Signed-off-by: Jean Privat <jean@pryen.org>

7 years agolib/popcorn: introduce Angular.js example
Alexandre Terrasa [Mon, 16 May 2016 21:14:12 +0000 (17:14 -0400)]
lib/popcorn: introduce Angular.js example

Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

7 years agolib/popcorn: introduce mongodb example
Alexandre Terrasa [Mon, 16 May 2016 22:50:59 +0000 (18:50 -0400)]
lib/popcorn: introduce mongodb example

Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

7 years agolib/popcorn: route tests
Alexandre Terrasa [Mon, 16 May 2016 19:05:08 +0000 (15:05 -0400)]
lib/popcorn: route tests

Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

7 years agolib/popcorn: router tests
Alexandre Terrasa [Mon, 16 May 2016 19:04:53 +0000 (15:04 -0400)]
lib/popcorn: router tests

Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

7 years agolib/popcorn: introduce middleware examples
Alexandre Terrasa [Mon, 16 May 2016 19:04:12 +0000 (15:04 -0400)]
lib/popcorn: introduce middleware examples

Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

7 years agolib/popcorn: introduce session example
Alexandre Terrasa [Mon, 16 May 2016 19:03:50 +0000 (15:03 -0400)]
lib/popcorn: introduce session example

Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

7 years agolib/popcorn: introduce handler examples
Alexandre Terrasa [Mon, 16 May 2016 19:03:15 +0000 (15:03 -0400)]
lib/popcorn: introduce handler examples

Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

7 years agolib/popcorn: introduce static_files examples
Alexandre Terrasa [Mon, 16 May 2016 19:01:31 +0000 (15:01 -0400)]
lib/popcorn: introduce static_files examples

Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

7 years agolib/popcorn: introduce routing examples
Alexandre Terrasa [Mon, 16 May 2016 19:00:31 +0000 (15:00 -0400)]
lib/popcorn: introduce routing examples

Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

7 years agolib/popcorn: introduce hello example
Alexandre Terrasa [Mon, 16 May 2016 18:59:10 +0000 (14:59 -0400)]
lib/popcorn: introduce hello example

Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

7 years agolib/popcorn: introduce base test features
Alexandre Terrasa [Mon, 16 May 2016 18:58:34 +0000 (14:58 -0400)]
lib/popcorn: introduce base test features

Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

7 years agolib/popcorn: introduce App implementation
Alexandre Terrasa [Mon, 16 May 2016 15:47:32 +0000 (11:47 -0400)]
lib/popcorn: introduce App implementation

Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

7 years agolib/popcorn: introduce default middlewares
Alexandre Terrasa [Mon, 16 May 2016 15:45:15 +0000 (11:45 -0400)]
lib/popcorn: introduce default middlewares

Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

7 years agolib/nitcorn: make session writable
Alexandre Terrasa [Mon, 16 May 2016 15:44:51 +0000 (11:44 -0400)]
lib/nitcorn: make session writable

Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

7 years agolib/popcorn: introduce pop_handlers
Alexandre Terrasa [Mon, 16 May 2016 15:44:26 +0000 (11:44 -0400)]
lib/popcorn: introduce pop_handlers

Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

7 years agolib/nitcorn: make file server "show_directory" an option
Alexandre Terrasa [Mon, 16 May 2016 15:43:36 +0000 (11:43 -0400)]
lib/nitcorn: make file server "show_directory" an option

Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

7 years agolib/nitcorn: introduce json media types
Alexandre Terrasa [Mon, 16 May 2016 15:42:58 +0000 (11:42 -0400)]
lib/nitcorn: introduce json media types

Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

7 years agolib/popcorn: introduce pop_routes
Alexandre Terrasa [Mon, 16 May 2016 15:40:10 +0000 (11:40 -0400)]
lib/popcorn: introduce pop_routes

Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

7 years agolib/nitcorn: redef to_s service on UriPart subclasses
Alexandre Terrasa [Mon, 16 May 2016 15:38:48 +0000 (11:38 -0400)]
lib/nitcorn: redef to_s service on UriPart subclasses

Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

7 years agolib/templates: fix typo in macro documentation
Alexandre Terrasa [Mon, 16 May 2016 15:32:54 +0000 (11:32 -0400)]
lib/templates: fix typo in macro documentation

Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

7 years ago.gitattributes: ignore trailing whitespaces in lib/popcorn/tests
Alexandre Terrasa [Tue, 17 May 2016 14:57:44 +0000 (10:57 -0400)]
.gitattributes: ignore trailing whitespaces in lib/popcorn/tests

Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

7 years agoMerge: More nitunit improvement
Jean Privat [Thu, 19 May 2016 19:12:28 +0000 (15:12 -0400)]
Merge: More nitunit improvement

The point of this serie is to make nitunit more usable and make it more sexy than tests.sh (or ad hoc test scripts) for libraries and programs.

## Highlight

* black box tests with .res files
* --nitc of NITC to locate a specific binary to use
* testcases are executed with some ulimits (to limit timeouts)
* the XML generated is more robust

## Black Box Testing

Sometimes, it is easier to validate a `TestCase` by comparing its output with a text file containing the expected result.

For each TestCase `test_bar` of a TestSuite `test_mod.nit`, if the corresponding file `test_mod.sav/test_bar.res` exists, then the output of the test is compared with the file.

The `diff(1)` command is used to perform the comparison.
The test is failed if non-zero is returned by `diff`.

~~~nit
module test_mod is test_suite
class TestFoo
        fun test_bar do
                print "Hello!"
        end
end
~~~

Where `test_mod.sav/test_bar.res` contains

~~~raw
Hello!
~~~

## Option `--nitc`

nitc compiler to use.

By default, nitunit tries to locate the `nitc` program with the environment variable `NITC` or heuristics.
The option is used to indicate a specific nitc binary.

Pull-Request: #2107
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>
Reviewed-by: Alexis Laferrière <alexis.laf@xymus.net>

7 years agoMerge: Mobile app for the Benitlux social network
Jean Privat [Thu, 19 May 2016 19:12:27 +0000 (15:12 -0400)]
Merge: Mobile app for the Benitlux social network

This is the long awaited Benitlux mobile app! This app lets you:

* View the current beer menu.
* Rate available beers.
* See ratings from the community and from your friends.
* Be notified of the daily beer menu.
* Be notified when a friend is on location.
* View a diff of the menu compared to your last visit.
* Debug the app and server by mixing in `src/client/features/debug.nit` at compilation.

The app is portable and fully adapted to Android and iOS. There's also a partially working GTK+ client for quick debugging, and makefile rules to get the pure prototype apps which useful for comparison and other relevant scientific purposes.

The adapted apps for Android and iOS varies depending on the features available on each platform:

* On Android, the app detects the wifi network of the bar and automatically notifies your friends that you are on location (if desired). It also launches a service at device boot to receive notifications from the server. These notifications are shown to the user using pure Java/Android APIs.

* On iOS, there is a button for the user to manually check in or out. There is also local user notifications, but they work only while the app is running. Both these features could be improved upon for a better user experience on iOS.

The source code is organized within `src/client` in two main folders. `views/`  holds the app windows and supporting views. `features/` holds the optional app features included differently per platform.

There is still a few issues to resolve. On iOS, the labels are not ellipsized correctly and the UI text is not updated after logging in. Some beer diffs are still weird and need to be tweaked. The server should be hardened against client version changes. Security should be double checked (This is for you @ppepos!). The GNU/Linux/GTK+ client does not support parallel HTTP request, so curl crashes on the main screen. There is also an ever increasing list of aesthetic changes!

The latest Benitlux features are not yet deployed on xymus.net. This will probably require to transfer data from the development DB to the production DB, or simply drop the development DB... So just so you are warned, the Android release app (the one on F-Droid) will not work right away.

Pull-Request: #2106
Reviewed-by: Jean Privat <jean@pryen.org>
Reviewed-by: Ait younes Mehdi Adel <overpex@gmail.com>

7 years agodocker/full: install android sdk/ndk
Jean Privat [Thu, 19 May 2016 19:06:16 +0000 (15:06 -0400)]
docker/full: install android sdk/ndk

Signed-off-by: Jean Privat <jean@pryen.org>

7 years agodocker/full: add nitunits
Jean Privat [Thu, 19 May 2016 19:04:51 +0000 (15:04 -0400)]
docker/full: add nitunits

Signed-off-by: Jean Privat <jean@pryen.org>

7 years agodocker/full: add postgresql
Jean Privat [Thu, 19 May 2016 19:04:27 +0000 (15:04 -0400)]
docker/full: add postgresql

Signed-off-by: Jean Privat <jean@pryen.org>

7 years agodocker: split into a basic and a full Docker
Jean Privat [Thu, 19 May 2016 19:02:56 +0000 (15:02 -0400)]
docker: split into a basic and a full Docker

Signed-off-by: Jean Privat <jean@pryen.org>

7 years agoMerge: doc: Fix a mispelled word in the parser’s README
Jean Privat [Thu, 19 May 2016 15:06:31 +0000 (11:06 -0400)]
Merge: doc: Fix a mispelled word in the parser’s README

Pull-Request: #2082
Reviewed-by: Jean Privat <jean@pryen.org>

7 years agoMerge: make the nitcatalog slightly more robust on person variations
Jean Privat [Thu, 19 May 2016 14:56:40 +0000 (10:56 -0400)]
Merge: make the nitcatalog slightly more robust on person variations

The various person-related fields were parsed verbatim.
So a slight change in spaces was enough to differentiate two persons.
Now the canonical person representation is used.

e.g. `Lucas Bajolet<r4pass@hotmail.com>` vs `Lucas Bajolet <r4pass@hotmail.com>
` is now the same person (hint: the change is the space between the `t` and the `<`).

Note that to present the original information,
 names/emails/url are still distinguished.

`Lucas Bajolet <r4pass@hotmail.com>`, `R4pass <r4pass@hotmail.com>
` and `Lucas Bajolet <lucas.bajolet@hotmail.com>
` are still 3 persons.

Pull-Request: #2103

7 years agoMerge: .gitignore: ignore .swo files
Jean Privat [Thu, 19 May 2016 14:56:38 +0000 (10:56 -0400)]
Merge: .gitignore: ignore .swo files

Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

Pull-Request: #2102
Reviewed-by: Jean Privat <jean@pryen.org>

7 years agonitunit: document black box (.res) testing
Jean Privat [Thu, 19 May 2016 13:08:16 +0000 (09:08 -0400)]
nitunit: document black box (.res) testing

Signed-off-by: Jean Privat <jean@pryen.org>

7 years agotests: extends test_nitunit4 with diff-based tests
Jean Privat [Thu, 19 May 2016 13:07:27 +0000 (09:07 -0400)]
tests: extends test_nitunit4 with diff-based tests

Signed-off-by: Jean Privat <jean@pryen.org>

7 years agonitunit: teach test_suite to compare outputs with a saved result file
Jean Privat [Thu, 19 May 2016 12:56:42 +0000 (08:56 -0400)]
nitunit: teach test_suite to compare outputs with a saved result file

Signed-off-by: Jean Privat <jean@pryen.org>

7 years agonitunit: update manpage with `--nitc`
Jean Privat [Thu, 19 May 2016 03:58:01 +0000 (23:58 -0400)]
nitunit: update manpage with `--nitc`

Signed-off-by: Jean Privat <jean@pryen.org>

7 years agotnitter & calculator: update packages.ini
Alexis Laferrière [Thu, 19 May 2016 14:14:37 +0000 (10:14 -0400)]
tnitter & calculator: update packages.ini

Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

7 years agocontrit/benitlux: update package.ini and intro F-Droid metadata
Alexis Laferrière [Thu, 19 May 2016 14:11:08 +0000 (10:11 -0400)]
contrit/benitlux: update package.ini and intro F-Droid metadata

Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

7 years agocontrib/benitlux: update README
Alexis Laferrière [Wed, 18 May 2016 13:03:50 +0000 (09:03 -0400)]
contrib/benitlux: update README

Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

7 years agocontrib/benitlux: intro iOS client
Alexis Laferrière [Mon, 14 Mar 2016 19:45:39 +0000 (15:45 -0400)]
contrib/benitlux: intro iOS client

Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

7 years agocontrib/benitlux: intro Android apps, pure prototype and adapted
Alexis Laferrière [Wed, 18 May 2016 15:21:33 +0000 (11:21 -0400)]
contrib/benitlux: intro Android apps, pure prototype and adapted

Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

7 years agocontrib/benitlux: intro Benitlux client prototype App
Alexis Laferrière [Sat, 12 Mar 2016 18:48:36 +0000 (13:48 -0500)]
contrib/benitlux: intro Benitlux client prototype App

Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

7 years agocontrib/benitlux: move server specific modules to the server folder
Alexis Laferrière [Tue, 17 May 2016 19:08:36 +0000 (15:08 -0400)]
contrib/benitlux: move server specific modules to the server folder

Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

7 years agotests: update nitunit tests
Jean Privat [Thu, 19 May 2016 03:50:11 +0000 (23:50 -0400)]
tests: update nitunit tests

Signed-off-by: Jean Privat <jean@pryen.org>

7 years agonitunit: filter the XML content (and trunc it if needed)
Jean Privat [Thu, 19 May 2016 03:49:54 +0000 (23:49 -0400)]
nitunit: filter the XML content (and trunc it if needed)

Signed-off-by: Jean Privat <jean@pryen.org>

7 years agonitunit: use a safe_exec function with high ulimits
Jean Privat [Thu, 19 May 2016 03:40:01 +0000 (23:40 -0400)]
nitunit: use a safe_exec function with high ulimits

Signed-off-by: Jean Privat <jean@pryen.org>

7 years agonitunit: add options to search the compiler
Jean Privat [Thu, 19 May 2016 02:36:33 +0000 (22:36 -0400)]
nitunit: add options to search the compiler

Signed-off-by: Jean Privat <jean@pryen.org>

7 years agonitunit: factorize the search of a compiler
Jean Privat [Thu, 19 May 2016 02:31:29 +0000 (22:31 -0400)]
nitunit: factorize the search of a compiler

Signed-off-by: Jean Privat <jean@pryen.org>

7 years agonitunit: prevent generated files to be part of the package
Jean Privat [Thu, 19 May 2016 02:24:14 +0000 (22:24 -0400)]
nitunit: prevent generated files to be part of the package

Signed-off-by: Jean Privat <jean@pryen.org>

7 years agolib/ios: fix ListLayout style
Alexis Laferrière [Fri, 15 Apr 2016 18:37:39 +0000 (14:37 -0400)]
lib/ios: fix ListLayout style

Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

7 years agolib/ios: fix `pop_window` on iOS
Alexis Laferrière [Wed, 18 May 2016 18:47:51 +0000 (14:47 -0400)]
lib/ios: fix `pop_window` on iOS

Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

7 years agolib/android: fix align to always be centered vertically
Alexis Laferrière [Sun, 1 May 2016 21:42:46 +0000 (17:42 -0400)]
lib/android: fix align to always be centered vertically

Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

7 years agoMerge: app.nit: navigate between windows with the back button
Jean Privat [Tue, 17 May 2016 20:17:43 +0000 (16:17 -0400)]
Merge: app.nit: navigate between windows with the back button

This should be the last big feature of _app.nit_ needed for my thesis!

Intro services to navigate between multiple windows of the same app.
Windows are added to a stack and popped back to the visible state on pressing the back key.
This behavior was implemented for Android by intercepting events raised by the "hardware" back key.
iOS offers the same features natively so there is no adaptation needed as of now.
On GNU/Linux with GTK+, a button is added to the window header when there's a window to go back to.

These feature will probably have to be tweaked in the future, but they are enough for the Benilux client app. Notably, the life-cylce of each individual window has to be reconsidered and we will probably need some adaptation on iOS to have a better integration.

This PR also fixes a few bugs. The `EditText` losing focus in a `ListLayout` is fixed by a change to the Android manifest file, and vertical layout should now look better on iOS.

I took the opportunity to add other key events while working on the Android back key support.
These will be useful when migrating games from the old low-level implementation on the NDK to our custom `NitActivity.java`.

Pull-Request: #2100
Reviewed-by: Jean Privat <jean@pryen.org>
Reviewed-by: Romain Chanoir <romain.chanoir@viacesi.fr>

7 years agoMerge: app.nit: intro `ToggleEvent`
Jean Privat [Tue, 17 May 2016 20:17:38 +0000 (16:17 -0400)]
Merge: app.nit: intro `ToggleEvent`

This PR adds an event when a checkbox is toggled. `ToggleEvent` is similar to the only previously existing event, `ButtonPressEvent`.

Pull-Request: #2099
Reviewed-by: Jean Privat <jean@pryen.org>

7 years agoMerge: lib/core: Fix substring issue in `ASCIIFlatString`
Jean Privat [Tue, 17 May 2016 20:17:32 +0000 (16:17 -0400)]
Merge: lib/core: Fix substring issue in `ASCIIFlatString`

A bug in the validation part of `ASCIIFlatString::substring` caused some substrings to be created with a negative length, which could be the cause of various negative side-effects.

In the example added in the substring test, this caused `stdout` to close due to a call to `fwrite` with a negative count, which was in turn converted to unsigned (I suspect this is undefined behaviour), provoking the closure of the stream in the nit part.

Reported by @Morriar
Close #2089

Pull-Request: #2091
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>
Reviewed-by: Jean Privat <jean@pryen.org>

7 years agoMerge: modelize: mark properties broken if they are a bad introduction (bad redef)
Jean Privat [Tue, 17 May 2016 20:17:28 +0000 (16:17 -0400)]
Merge: modelize: mark properties broken if they are a bad introduction (bad redef)

Some broken redefinitions of properties caused the modelize phase to crash.

An infrastructure exists to prevent the use of such broken entities: the `is_broken` attributes. But they have to be set and used to be effective.

So this PR sets the `is_broken` flag on some forgotten error paths, then prevents further processing if `is_broken` is set.

Pull-Request: #2078
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>

7 years agoMerge: model: introduce model_json
Jean Privat [Tue, 17 May 2016 20:17:25 +0000 (16:17 -0400)]
Merge: model: introduce model_json

This PR makes all model entities Jsonable when `model_json` is imported.

Not sure if I was supposed to use the serialization process or not in this case? @xymus what do you think?

This is mostly hand picked services chosen to provide a comprehensive model representation usable by other tools like nitdoc, nitx, web tools or else.

Pull-Request: #2024
Reviewed-by: Jean Privat <jean@pryen.org>

7 years agomake the nitcatalog slightly more robust on person variations
Jean Privat [Tue, 17 May 2016 20:16:23 +0000 (16:16 -0400)]
make the nitcatalog slightly more robust on person variations

The various person-related fields were parsed verbatim.
So a slight change in spaces was enough to differentiate two persons.
Now the canonical person representation is used.

e.g. `Lucas Bajolet<r4pass@hotmail.com>` vs `Lucas Bajolet <r4pass@hotmail.com>
` is now the same person (hint: the change is the space between the `t` and the `<`).

Note that to present the original information,
 names/emails/url are still distinguished.

`Lucas Bajolet <r4pass@hotmail.com>`, `R4pass <r4pass@hotmail.com>
` and `Lucas Bajolet <lucas.bajolet@hotmail.com>
` are still 3 persons.

Signed-off-by: Jean Privat <jean@pryen.org>