From: Jean Privat Date: Tue, 15 Sep 2015 16:57:16 +0000 (-0400) Subject: Merge: Clean UTF-8 string update X-Git-Tag: v0.7.8~23 X-Git-Url: http://nitlanguage.org?hp=2a731344f2c760b78d5144f92ab73890320ce37a Merge: Clean UTF-8 string update Since quite some time now we've had the cleaning function for Bytes that ensured that what was coming from the exterior was clean and could be transformed safely to a String. This is now generalized to any NativeString, and the clean function will be called each time a NativeString is `to_s`'d At the same time, `clean_utf8` is now better performing (for `Files::read_all`, Ir per call is roughly 40% less than before), which limits the impacts of the new strategy. Furthermore, the string produced by `NativeString::clean_utf8` has its length calculated which saves time on later operations on the string. It also limits the number of calls by avoiding allocations if not necessary (if the string is already clean, which should happen a lot more often than not). As for performances, Valgrind `./bin/nitc src/nitc.nit`: Before: 14.040 GIr After: 13.859 GIr Time, best of 10 for `./bin/nitc src/nitc.nit -o bin/nitc`: Before: 0m4.989s After: 0m4.933s Time, best of 10 for `./bin/nitc --semi-global src/nitc.nit -o bin/nitc`: Before: 0m4.696s After: 0m4.691s Pretty much equivalent in real time, and a bit better in Valgrind, not bad considering every String is now cleaner than ever ! Pull-Request: #1705 Reviewed-by: Jean Privat Reviewed-by: Alexis Laferrière --- diff --git a/contrib/benitlux/project.ini b/contrib/benitlux/package.ini similarity index 97% rename from contrib/benitlux/project.ini rename to contrib/benitlux/package.ini index a9eff3b..53acc9d 100644 --- a/contrib/benitlux/project.ini +++ b/contrib/benitlux/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=benitlux tags=network maintainer=Alexis Laferrière diff --git a/contrib/brainfuck/project.ini b/contrib/brainfuck/package.ini similarity index 96% rename from contrib/brainfuck/project.ini rename to contrib/brainfuck/package.ini index 440c8d5..59c69b6 100644 --- a/contrib/brainfuck/project.ini +++ b/contrib/brainfuck/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=brainfuck tags=language maintainer=Lucas Bajolet diff --git a/contrib/crazy_moles/Makefile b/contrib/crazy_moles/Makefile index 3fc90f7..049e851 100644 --- a/contrib/crazy_moles/Makefile +++ b/contrib/crazy_moles/Makefile @@ -4,11 +4,14 @@ bin/moles: $(shell ../../bin/nitls -M src/moles_linux.nit) assets/images/drawing mkdir -p bin ../../bin/nitc -o bin/moles src/moles_linux.nit +android: bin/moles.apk bin/moles.apk: android-icons $(shell ../../bin/nitls -M src/moles_android.nit) assets/images/drawing.png mkdir -p bin ../../bin/nitc -o bin/moles.apk src/moles_android.nit -android: bin/moles.apk +android-release: android-icons $(shell ../../bin/nitls -M src/moles_android.nit) assets/images/drawing.png + mkdir -p bin + ../../bin/nitc -o bin/moles.apk src/moles_android.nit --release ../inkscape_tools/bin/svg_to_icons: $(MAKE) -C ../inkscape_tools diff --git a/contrib/crazy_moles/project.ini b/contrib/crazy_moles/package.ini similarity index 97% rename from contrib/crazy_moles/project.ini rename to contrib/crazy_moles/package.ini index 0369bd7..42eae16 100644 --- a/contrib/crazy_moles/project.ini +++ b/contrib/crazy_moles/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=crazy_moles tags=game maintainer=Alexis Laferrière diff --git a/contrib/friendz/Makefile b/contrib/friendz/Makefile index f236a1d..0cedb4c 100644 --- a/contrib/friendz/Makefile +++ b/contrib/friendz/Makefile @@ -4,11 +4,18 @@ linux: mkdir -p bin ../../bin/nitc -o bin/friendz src/friendz_linux.nit -android: - mkdir -p bin res - ../inkscape_tools/bin/svg_to_icons art/icon.svg --android --out res/ +android: res/drawable-hdpi/icon.png + mkdir -p bin ../../bin/nitc -o bin/friendz.apk src/friendz_android.nit +android-release: res/drawable-hdpi/icon.png + mkdir -p bin + ../../bin/nitc -o bin/friendz.apk src/friendz_android.nit --release + +res/drawable-hdpi/icon.png: art/icon.svg + mkdir -p res + ../inkscape_tools/bin/svg_to_icons art/icon.svg --android --out res/ + doc: mkdir -p doc ../../bin/nitdoc -d doc/ src/friendz.nit src/friendz_linux.nit diff --git a/contrib/friendz/project.ini b/contrib/friendz/package.ini similarity index 96% rename from contrib/friendz/project.ini rename to contrib/friendz/package.ini index dfb04ba..b1398f2 100644 --- a/contrib/friendz/project.ini +++ b/contrib/friendz/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=friendz tags=game maintainer=Jean Privat diff --git a/contrib/friendz/res/raw/music.ogg b/contrib/friendz/res/raw/music.ogg new file mode 100644 index 0000000..8dcfa3b Binary files /dev/null and b/contrib/friendz/res/raw/music.ogg differ diff --git a/contrib/github_merge.ini b/contrib/github_merge.ini index 0615986..8f206bf 100644 --- a/contrib/github_merge.ini +++ b/contrib/github_merge.ini @@ -1,4 +1,4 @@ -[project] +[package] name=github_merge tags=cli maintainer=Jean Privat diff --git a/contrib/github_search_for_jni/project.ini b/contrib/github_search_for_jni/package.ini similarity index 97% rename from contrib/github_search_for_jni/project.ini rename to contrib/github_search_for_jni/package.ini index 5b5c36b..0196d6f 100644 --- a/contrib/github_search_for_jni/project.ini +++ b/contrib/github_search_for_jni/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=github_search_for_jni tags=cli maintainer=Alexis Laferrière diff --git a/contrib/header_keeper/project.ini b/contrib/header_keeper/package.ini similarity index 97% rename from contrib/header_keeper/project.ini rename to contrib/header_keeper/package.ini index f2783c0..549bbb6 100644 --- a/contrib/header_keeper/project.ini +++ b/contrib/header_keeper/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=header_keeper tags=devel,cli maintainer=Alexis Laferrière diff --git a/contrib/inkscape_tools/project.ini b/contrib/inkscape_tools/package.ini similarity index 97% rename from contrib/inkscape_tools/project.ini rename to contrib/inkscape_tools/package.ini index d8cc3c4..f553cd5 100644 --- a/contrib/inkscape_tools/project.ini +++ b/contrib/inkscape_tools/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=inkscape_tools tags=devel,cli maintainer=Alexis Laferrière diff --git a/contrib/inkscape_tools/tests/projects.ini b/contrib/inkscape_tools/tests/packages.ini similarity index 100% rename from contrib/inkscape_tools/tests/projects.ini rename to contrib/inkscape_tools/tests/packages.ini diff --git a/contrib/jwrapper/Makefile b/contrib/jwrapper/Makefile index 34faa7a..7c41505 100644 --- a/contrib/jwrapper/Makefile +++ b/contrib/jwrapper/Makefile @@ -10,7 +10,7 @@ src/javap_test_parser.nit: ../nitcc/src/nitcc grammar/javap.sablecc mv javap* gen/ src/serial.nit: $(shell ../../bin/nitls -M src/jwrapper.nit) - ../../bin/nitserial -o src/serial.nit -d project src/jwrapper.nit + ../../bin/nitserial -o src/serial.nit -d package src/jwrapper.nit bin/jwrapper: src/javap_test_parser.nit src/serial.nit $(shell ../../bin/nitls -M src/jwrapper.nit) ../../bin/nitc mkdir -p bin diff --git a/contrib/jwrapper/tests/projects.ini b/contrib/jwrapper/examples/packages.ini similarity index 100% rename from contrib/jwrapper/tests/projects.ini rename to contrib/jwrapper/examples/packages.ini diff --git a/contrib/jwrapper/project.ini b/contrib/jwrapper/package.ini similarity index 97% rename from contrib/jwrapper/project.ini rename to contrib/jwrapper/package.ini index b43cd0e..adaed16 100644 --- a/contrib/jwrapper/project.ini +++ b/contrib/jwrapper/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=jwrapper tags=java,devel,cli maintainer=Alexis Laferrière diff --git a/contrib/nitcc/tests/projects.ini b/contrib/jwrapper/tests/packages.ini similarity index 100% rename from contrib/nitcc/tests/projects.ini rename to contrib/jwrapper/tests/packages.ini diff --git a/contrib/mnit_test/Makefile b/contrib/mnit_test/Makefile index 73ed663..a198c27 100644 --- a/contrib/mnit_test/Makefile +++ b/contrib/mnit_test/Makefile @@ -9,5 +9,10 @@ android: ../../bin/nitc -o bin/complete.apk src/complete_simple_android.nit --semi-global ../../bin/nitc -o bin/minimal.apk src/simple_android.nit --semi-global +android-release: + mkdir -p bin + ../../bin/nitc -o bin/complete.apk src/complete_simple_android.nit --semi-global --release + ../../bin/nitc -o bin/minimal.apk src/simple_android.nit --semi-global --release + clean: rm -rf bin diff --git a/contrib/mnit_test/project.ini b/contrib/mnit_test/package.ini similarity index 97% rename from contrib/mnit_test/project.ini rename to contrib/mnit_test/package.ini index e595abe..29856ff 100644 --- a/contrib/mnit_test/project.ini +++ b/contrib/mnit_test/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=mnit_test tags= maintainer=Alexis Laferrière diff --git a/contrib/neo_doxygen/project.ini b/contrib/neo_doxygen/package.ini similarity index 97% rename from contrib/neo_doxygen/project.ini rename to contrib/neo_doxygen/package.ini index 9f5ceaf..7ca5877 100644 --- a/contrib/neo_doxygen/project.ini +++ b/contrib/neo_doxygen/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=neo_doxygen tags=devel,cli maintainer=Jean-Christophe Beaupré diff --git a/contrib/nitcc/project.ini b/contrib/nitcc/package.ini similarity index 96% rename from contrib/nitcc/project.ini rename to contrib/nitcc/package.ini index bdc1258..900f9d7 100644 --- a/contrib/nitcc/project.ini +++ b/contrib/nitcc/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=nitcc tags=devel,cli maintainer=Jean Privat diff --git a/contrib/projects.ini b/contrib/nitcc/tests/package.ini similarity index 100% rename from contrib/projects.ini rename to contrib/nitcc/tests/package.ini diff --git a/contrib/nitester/project.ini b/contrib/nitester/package.ini similarity index 97% rename from contrib/nitester/project.ini rename to contrib/nitester/package.ini index 10897ac..8c73e01 100644 --- a/contrib/nitester/project.ini +++ b/contrib/nitester/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=nitester tags=devel,cli maintainer=Alexis Laferrière diff --git a/contrib/nitiwiki/examples/nitiwiki/config.ini b/contrib/nitiwiki/examples/nitiwiki/config.ini index 315462d..bc96f38 100644 --- a/contrib/nitiwiki/examples/nitiwiki/config.ini +++ b/contrib/nitiwiki/examples/nitiwiki/config.ini @@ -3,3 +3,4 @@ wiki.desc=proudly powered by nit wiki.logo=assets/logo.png wiki.root_dir=. wiki.rsync_dir=moz-code.org:nitiwiki/ +wiki.highlighter=./highlighter.sh "$1" diff --git a/contrib/nitiwiki/examples/nitiwiki/highlighter.sh b/contrib/nitiwiki/examples/nitiwiki/highlighter.sh new file mode 100755 index 0000000..57aaf45 --- /dev/null +++ b/contrib/nitiwiki/examples/nitiwiki/highlighter.sh @@ -0,0 +1,36 @@ +#!/bin/sh + +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Example of an external highlighter that dispatch on various command +# according to the argument + +# meta is the argument +meta=$1 + +# raw is a synonym of txt +test "$meta" = "raw" && meta=txt + +# if `pandoc` then process through the `pandoc` command. +if test "$meta" = "pandoc"; then + exec pandoc -t html +fi + +# Else, try `highlight` +highlight --fragment -S "$meta" --inline-css --enclose-pre || + # Or `source-highlight` + source-highlight -s "$meta" +out=$? +exit $out diff --git a/contrib/nitiwiki/examples/nitiwiki/pages/block.md b/contrib/nitiwiki/examples/nitiwiki/pages/block.md new file mode 100644 index 0000000..d0daaba --- /dev/null +++ b/contrib/nitiwiki/examples/nitiwiki/pages/block.md @@ -0,0 +1,36 @@ +# Test of code highlighting + +A basic block. + + print(["hello", "world"].join(", ")) + +A fenced block. + +~~~ +print(["hello", "world"].join(", ")) +~~~ + +A fenced block with metainfo, so it can be highlighted with an external tool. + +~~~html + + + +
HelloWorld
+~~~ + +A special block where the rendering is delegated to pandoc. +For instance, to render tables. + +~~~pandoc +what how +------ ----- +hello 10 +world 9001 +~~~ + +This try some exploit +~~~raw'"; echo pwned >&2 # +Hello
+World +~~~ diff --git a/contrib/nitiwiki/project.ini b/contrib/nitiwiki/package.ini similarity index 97% rename from contrib/nitiwiki/project.ini rename to contrib/nitiwiki/package.ini index 0ebf3a8..83efead 100644 --- a/contrib/nitiwiki/project.ini +++ b/contrib/nitiwiki/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=nitiwiki tags=web,cli maintainer=Alexandre Terrasa diff --git a/contrib/nitiwiki/src/markdown_highlight.nit b/contrib/nitiwiki/src/markdown_highlight.nit new file mode 100644 index 0000000..08751b0 --- /dev/null +++ b/contrib/nitiwiki/src/markdown_highlight.nit @@ -0,0 +1,99 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Extends the wiki with an external highlighter (or any processor) for code blocks +module markdown_highlight +import wiki_links + +redef class WikiConfig + # External highlighter command called to process block code. + # + # * key: `wiki.highlighter` + # * default: empty string, that means no external highlighter + # * example: `highlight --fragment -S "$1" --inline-css --enclose-pre` + # + # The external highlighter is a shell command invoked with `sh -c`. + # The meta information of the fence is passed as `$1`. + # *Important*: `$1` is given as is, thus is tainted. You SHOULD protect it with quotes in the command. + # + # By default, the highlighter is only called on fenced block code with a meta information. + # See `wiki.highlighter.default` to force the invocation of the highlighter on any code block. + # + # The output of the command will be inserted as is in the generated document. + # Therefore it is expected that the command returns a valid, complete and balanced HTML fragment. + # If the highlighter returns nothing (empty output), the internal rendering is used as a fall-back + # (as if the option was not set). + # + # Advanced usages can invoke a custom shell script instead of a standard command to + # check the argument, filter it, dispatch to various advanced commands, implement ad-hoc behaviors, etc. + var highlighter: String is lazy do + return value_or_default("wiki.highlighter", "") + end + + # Default meta (i.e. language) to use to call the external highlighter. + # + # * key: `wiki.highlighter.default` + # * default: empty string, that means no default meta information. + # * example: `nit` + # + # When set, this configuration forces the external highlighter (see `wiki.highlighter`) + # to be called also on basic code block (with the indentation) and plain fenced code + # blocks (without meta information). + # + # The value is used as the `$1` argument of the configured highlighter command. + # + # Note: has no effect if `wiki.highlighter` is not set. + var highlighter_default: String is lazy do + return value_or_default("wiki.highlighter.default", "") + end +end + +redef class NitiwikiDecorator + # Extends special cases for meta in fences + redef fun add_code(v, block) do + var highlighter = wiki.config.highlighter + + # No highlighter, then defaults + if highlighter.is_empty then + super + return + end + + var code = block.raw_content + var meta = block.meta or else wiki.config.highlighter_default + + # No meta nor forced meta, then defaults + if meta.is_empty then + super + return + end + + # Execute the command + wiki.message("Executing `{highlighter}` `{meta}` (in {context.src_path.as(not null)})", 2) + var proc = new ProcessDuplex("sh", "-c", highlighter, "", meta.to_s) + var res = proc.write_and_read(code) + if proc.status != 0 then + wiki.message("Warning: `{highlighter}` `{meta}` returned {proc.status} (in {context.src_path.as(not null)})", 0) + end + + # Check the result + if res.is_empty then + # No result, then defaults + wiki.message(" `{highlighter}` produced nothing, process internally instead (in {context.src_path.as(not null)})", 2) + super + return + end + v.add(res) + end +end diff --git a/contrib/nitiwiki/src/nitiwiki.nit b/contrib/nitiwiki/src/nitiwiki.nit index 71ab129..c5c6ebe 100644 --- a/contrib/nitiwiki/src/nitiwiki.nit +++ b/contrib/nitiwiki/src/nitiwiki.nit @@ -16,6 +16,7 @@ module nitiwiki import wiki_html +import markdown_highlight # Locate nit directory private fun compute_nit_dir(opt_nit_dir: OptionString): String do diff --git a/contrib/nitiwiki/src/wiki_base.nit b/contrib/nitiwiki/src/wiki_base.nit index 5f093a0..70cf35f 100644 --- a/contrib/nitiwiki/src/wiki_base.nit +++ b/contrib/nitiwiki/src/wiki_base.nit @@ -615,7 +615,7 @@ class WikiConfig super ConfigTree # Returns the config value at `key` or return `default` if no key was found. - private fun value_or_default(key: String, default: String): String do + protected fun value_or_default(key: String, default: String): String do return self[key] or else default end diff --git a/contrib/nitiwiki/src/wiki_links.nit b/contrib/nitiwiki/src/wiki_links.nit index 340ec74..efb9f78 100644 --- a/contrib/nitiwiki/src/wiki_links.nit +++ b/contrib/nitiwiki/src/wiki_links.nit @@ -214,7 +214,8 @@ class NitiwikiMdProcessor end end -private class NitiwikiDecorator +# The decorator associated to `MarkdownProcessor`. +class NitiwikiDecorator super HTMLDecorator # Wiki used to resolve links. diff --git a/contrib/nitrpg/project.ini b/contrib/nitrpg/package.ini similarity index 97% rename from contrib/nitrpg/project.ini rename to contrib/nitrpg/package.ini index e697771..125e96c 100644 --- a/contrib/nitrpg/project.ini +++ b/contrib/nitrpg/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=nitrpg tags=devel,web,cli maintainer=Alexandre Terrasa diff --git a/contrib/objcwrapper/project.ini b/contrib/objcwrapper/package.ini similarity index 97% rename from contrib/objcwrapper/project.ini rename to contrib/objcwrapper/package.ini index 4359608..e2ef8d3 100644 --- a/contrib/objcwrapper/project.ini +++ b/contrib/objcwrapper/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=objcwrapper tags=devel,cli maintainer=Alexis Laferrière diff --git a/contrib/online_ide/project.ini b/contrib/online_ide/package.ini similarity index 97% rename from contrib/online_ide/project.ini rename to contrib/online_ide/package.ini index 2729576..ee1afbd 100644 --- a/contrib/online_ide/project.ini +++ b/contrib/online_ide/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=online_ide tags=devel,web maintainer=Johan Kayser diff --git a/contrib/opportunity/project.ini b/contrib/opportunity/package.ini similarity index 97% rename from contrib/opportunity/project.ini rename to contrib/opportunity/package.ini index f19f154..9e3dae9 100644 --- a/contrib/opportunity/project.ini +++ b/contrib/opportunity/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=opportunity tags=web maintainer=Lucas Bajolet diff --git a/examples/projects.ini b/contrib/packages.ini similarity index 100% rename from examples/projects.ini rename to contrib/packages.ini diff --git a/contrib/pep8analysis/project.ini b/contrib/pep8analysis/package.ini similarity index 97% rename from contrib/pep8analysis/project.ini rename to contrib/pep8analysis/package.ini index 9a50402..5f5fba5 100644 --- a/contrib/pep8analysis/project.ini +++ b/contrib/pep8analysis/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=pep8analysis tags=educ,web,cli maintainer=Alexis Laferrière diff --git a/contrib/physical_interface_for_mpd_on_rpi/project.ini b/contrib/physical_interface_for_mpd_on_rpi/package.ini similarity index 97% rename from contrib/physical_interface_for_mpd_on_rpi/project.ini rename to contrib/physical_interface_for_mpd_on_rpi/package.ini index 5c1fe75..c844171 100644 --- a/contrib/physical_interface_for_mpd_on_rpi/project.ini +++ b/contrib/physical_interface_for_mpd_on_rpi/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=physical_interface_for_mpd_on_rpi tags=embedded,cli maintainer=Alexis Laferrière diff --git a/contrib/refund/project.ini b/contrib/refund/package.ini similarity index 97% rename from contrib/refund/project.ini rename to contrib/refund/package.ini index 6e7591b..9332fd0 100644 --- a/contrib/refund/project.ini +++ b/contrib/refund/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=refund tags=example,cli maintainer=Alexandre Terrasa diff --git a/contrib/rss_downloader/project.ini b/contrib/rss_downloader/package.ini similarity index 97% rename from contrib/rss_downloader/project.ini rename to contrib/rss_downloader/package.ini index 162816a..2dee4f0 100644 --- a/contrib/rss_downloader/project.ini +++ b/contrib/rss_downloader/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=rss_downloader tags=network,cli maintainer=Alexis Laferrière diff --git a/contrib/simplan/project.ini b/contrib/simplan/package.ini similarity index 96% rename from contrib/simplan/project.ini rename to contrib/simplan/package.ini index bab2310..1f4e49a 100644 --- a/contrib/simplan/project.ini +++ b/contrib/simplan/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=simplan tags=ai,example,cli maintainer=Jean Privat diff --git a/contrib/sort_downloads/project.ini b/contrib/sort_downloads/package.ini similarity index 97% rename from contrib/sort_downloads/project.ini rename to contrib/sort_downloads/package.ini index acd2fe2..2f75eb3 100644 --- a/contrib/sort_downloads/project.ini +++ b/contrib/sort_downloads/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=sort_downloads tags=cli maintainer=Alexis Laferrière diff --git a/contrib/tinks/Makefile b/contrib/tinks/Makefile index b22453a..ee13360 100644 --- a/contrib/tinks/Makefile +++ b/contrib/tinks/Makefile @@ -32,9 +32,12 @@ src/server/server_serialize.nit: $(shell ../../bin/nitls -M src/server/dedicated ../../bin/nitserial -o src/server/server_serialize.nit src/server/dedicated.nit # Android +android: bin/tinks.apk bin/tinks.apk: assets/images/drawing.png src/client/client_serialize.nit res/drawable-ldpi/icon.png $(shell ../../bin/nitls -M src/client/android_client.nit) - ../../bin/nitc -o bin/tinks.apk src/client/android_client.nit -m src/client/client_serialize.nit --compile-dir nit_compile - adb install -r bin/tinks.apk + ../../bin/nitc -o bin/tinks.apk src/client/android_client.nit -m src/client/client_serialize.nit + +android-release: assets/images/drawing.png src/client/client_serialize.nit res/drawable-ldpi/icon.png $(shell ../../bin/nitls -M src/client/android_client.nit) + ../../bin/nitc -o bin/tinks.apk src/client/android_client.nit -m src/client/client_serialize.nit --release res/drawable-ldpi/icon.png: art/icon.svg ../inkscape_tools/bin/svg_to_icons art/icon.svg --android --out res/ diff --git a/contrib/tinks/art/icon.svg b/contrib/tinks/art/icon.svg index 20a590d..32229e4 100644 --- a/contrib/tinks/art/icon.svg +++ b/contrib/tinks/art/icon.svg @@ -241,8 +241,8 @@ inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="1.979899" - inkscape:cx="107.98668" - inkscape:cy="65.759563" + inkscape:cx="357.89925" + inkscape:cy="19.247995" inkscape:document-units="px" inkscape:current-layer="0splash" showgrid="false" @@ -305,9 +305,10 @@ transform="matrix(0.9571749,0,0,0.9571749,14.241487,126.08446)"> + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccccccccccccc" /> + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccccccccccccc" /> + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccccccc" /> TINKS! + TINKS! diff --git a/contrib/tinks/project.ini b/contrib/tinks/package.ini similarity index 96% rename from contrib/tinks/project.ini rename to contrib/tinks/package.ini index ec34d3a..dc04026 100644 --- a/contrib/tinks/project.ini +++ b/contrib/tinks/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=tinks tags=game maintainer=Alexis Laferrière diff --git a/contrib/tnitter/project.ini b/contrib/tnitter/package.ini similarity index 96% rename from contrib/tnitter/project.ini rename to contrib/tnitter/package.ini index d589d1f..42a426c 100644 --- a/contrib/tnitter/project.ini +++ b/contrib/tnitter/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=tnitter tags=web maintainer=Alexis Laferrière diff --git a/contrib/wiringPi/project.ini b/contrib/wiringPi/package.ini similarity index 97% rename from contrib/wiringPi/project.ini rename to contrib/wiringPi/package.ini index b4c8c48..8afbf8b 100644 --- a/contrib/wiringPi/project.ini +++ b/contrib/wiringPi/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=wiringPi tags=embedded,wrapper maintainer=Alexandre Terrasa diff --git a/examples/calculator/art/icon.svg b/examples/calculator/art/icon.svg index ccd533c..618dc3d 100644 --- a/examples/calculator/art/icon.svg +++ b/examples/calculator/art/icon.svg @@ -24,9 +24,9 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="0.9899495" - inkscape:cx="58.64005" - inkscape:cy="380.00465" + inkscape:zoom="1.4" + inkscape:cx="160.56125" + inkscape:cy="282.40083" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="false" @@ -97,17 +97,14 @@ width="211.42856" id="rect2995" style="fill:#cccccc;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none" /> - + + id="text2997"> + + - = + id="text3013"> + + diff --git a/examples/calculator/project.ini b/examples/calculator/package.ini similarity index 97% rename from examples/calculator/project.ini rename to examples/calculator/package.ini index 28b52fb..adeb755 100644 --- a/examples/calculator/project.ini +++ b/examples/calculator/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=calculator tags=example maintainer=Alexis Laferrière diff --git a/examples/circular_list.ini b/examples/circular_list.ini index c5ac8ce..0cffc3a 100644 --- a/examples/circular_list.ini +++ b/examples/circular_list.ini @@ -1,4 +1,4 @@ -[project] +[package] name=circular_list tags=algo,example maintainer=Jean Privat diff --git a/examples/clock.ini b/examples/clock.ini index 4edb9d3..5438b51 100644 --- a/examples/clock.ini +++ b/examples/clock.ini @@ -1,4 +1,4 @@ -[project] +[package] name=clock tags=example maintainer=Jean Privat diff --git a/examples/clock_more.ini b/examples/clock_more.ini index 669c71d..d57de66 100644 --- a/examples/clock_more.ini +++ b/examples/clock_more.ini @@ -1,4 +1,4 @@ -[project] +[package] name=clock_more tags=example maintainer=Jean Privat diff --git a/examples/draw_operation.ini b/examples/draw_operation.ini index 31772ef..189e88d 100644 --- a/examples/draw_operation.ini +++ b/examples/draw_operation.ini @@ -1,4 +1,4 @@ -[project] +[package] name=draw_operation tags= maintainer=Alexis Laferrière diff --git a/examples/extern_methods.ini b/examples/extern_methods.ini index 460e02b..bba626e 100644 --- a/examples/extern_methods.ini +++ b/examples/extern_methods.ini @@ -1,4 +1,4 @@ -[project] +[package] name=extern_methods tags=wrapper,example maintainer=Alexis Laferrière diff --git a/examples/fibonacci.ini b/examples/fibonacci.ini index 303d9ed..4508f69 100644 --- a/examples/fibonacci.ini +++ b/examples/fibonacci.ini @@ -1,4 +1,4 @@ -[project] +[package] name=fibonacci tags=example maintainer=Jean Privat diff --git a/examples/hello_world.ini b/examples/hello_world.ini index d666cf2..72f0fb6 100644 --- a/examples/hello_world.ini +++ b/examples/hello_world.ini @@ -1,4 +1,4 @@ -[project] +[package] name=hello_world tags=example maintainer=Jean Privat diff --git a/examples/int_stack.ini b/examples/int_stack.ini index 7b8b9fc..6248cbe 100644 --- a/examples/int_stack.ini +++ b/examples/int_stack.ini @@ -1,4 +1,4 @@ -[project] +[package] name=int_stack tags=example maintainer=Jean Privat diff --git a/examples/leapfrog/project.ini b/examples/leapfrog/package.ini similarity index 96% rename from examples/leapfrog/project.ini rename to examples/leapfrog/package.ini index 56c05d5..eefa485 100644 --- a/examples/leapfrog/project.ini +++ b/examples/leapfrog/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=leapfrog tags=game,terminal maintainer=Jean Privat diff --git a/examples/mnit_ballz/Makefile b/examples/mnit_ballz/Makefile index 337c69a..b9a0dfc 100644 --- a/examples/mnit_ballz/Makefile +++ b/examples/mnit_ballz/Makefile @@ -1,4 +1,4 @@ -default: android +default: linux ../../contrib/inkscape_tools/bin/svg_to_icons: $(MAKE) -C ../../contrib/inkscape_tools @@ -7,6 +7,14 @@ android: icon mkdir -p bin ../../bin/nitc -o bin/ballz.apk src/ballz_android.nit +android-release: icon + mkdir -p bin + ../../bin/nitc -o bin/ballz.apk src/ballz_android.nit --release + +linux: + mkdir -p bin + ../../bin/nitc -o bin/ballz src/ballz_linux.nit + icon: ../../contrib/inkscape_tools/bin/svg_to_icons mkdir -p res ../../contrib/inkscape_tools/bin/svg_to_icons art/ball.svg --android --out res/ diff --git a/examples/mnit_ballz/assets/images/horizontal_wall.png b/examples/mnit_ballz/assets/images/horizontal_wall.png new file mode 100644 index 0000000..7ba6c68 Binary files /dev/null and b/examples/mnit_ballz/assets/images/horizontal_wall.png differ diff --git a/examples/mnit_ballz/assets/images/vertical_wall.png b/examples/mnit_ballz/assets/images/vertical_wall.png new file mode 100644 index 0000000..da42302 Binary files /dev/null and b/examples/mnit_ballz/assets/images/vertical_wall.png differ diff --git a/examples/mnit_ballz/project.ini b/examples/mnit_ballz/package.ini similarity index 97% rename from examples/mnit_ballz/project.ini rename to examples/mnit_ballz/package.ini index 7a252c1..7314aeb 100644 --- a/examples/mnit_ballz/project.ini +++ b/examples/mnit_ballz/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=mnit_ballz tags=game maintainer=Romain Chanoir diff --git a/examples/mnit_ballz/res/raw/bounce.ogg b/examples/mnit_ballz/res/raw/bounce.ogg new file mode 100644 index 0000000..bcd66dd Binary files /dev/null and b/examples/mnit_ballz/res/raw/bounce.ogg differ diff --git a/examples/mnit_ballz/res/raw/walld.wav b/examples/mnit_ballz/res/raw/walld.wav new file mode 100644 index 0000000..f61d065 Binary files /dev/null and b/examples/mnit_ballz/res/raw/walld.wav differ diff --git a/examples/mnit_ballz/src/assets.nit b/examples/mnit_ballz/src/assets.nit new file mode 100644 index 0000000..e823284 --- /dev/null +++ b/examples/mnit_ballz/src/assets.nit @@ -0,0 +1,49 @@ +# this file is part of NIT ( http://www.nitlanguage.org ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# All the assets needed by the appplication, regrouped in one class +module assets + +import app::audio +import mnit::assets + + +# Contains all the assets +class Assets + + # Sound for the wall destruction + var wall_destruction = new Sound("walld.wav") + + # Sound when the ball bounce + var bounce = new Sound("bounce.ogg") + + # Image of the ball + var ball: Image is noinit + + # Image for the horizontal walls + var horizontal_wall: Image is noinit + + # Image for the vertical walls + var vertical_wall: Image is noinit + + # Loads all the assets + fun load do + ball = app.load_image("images/ball.png") + horizontal_wall = app.load_image("images/horizontal_wall.png") + vertical_wall = app.load_image("images/vertical_wall.png") + wall_destruction.load + bounce.load + end +end diff --git a/examples/mnit_ballz/src/ballz_android.nit b/examples/mnit_ballz/src/ballz_android.nit index 249ee68..dc934e7 100644 --- a/examples/mnit_ballz/src/ballz_android.nit +++ b/examples/mnit_ballz/src/ballz_android.nit @@ -1,7 +1,5 @@ # this file is part of NIT ( http://www.nitlanguage.org ). # -# Copyright 2014 Romain Chanoir -# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at @@ -14,22 +12,26 @@ # See the License for the specific language governing permissions and # limitations under the License. + +# Android part of mnit_ballz module ballz_android is - app_version(1, 0, git_revision) + app_version(0, 2, git_revision) app_name("Ballz") + app_namespace "org.nitlanguage.ballz" + android_api_target 19 end import android::portrait - -import game_logic +import android::sensors +import display +import mnit::android redef class App - var screen: nullable Screen + # The game + var game: nullable Game is noautoinit - redef fun run - do - sensors_support_enabled = true + redef fun run do accelerometer.enabled = true accelerometer.event_rate = 10000 magnetic_field.enabled = true @@ -37,33 +39,72 @@ redef class App light.enabled = true proximity.enabled = true maximum_fps = 50 - + sensors_support_enabled = true super end redef fun on_create do super - screen = new Screen(self, display.as(Display)) + game = new Game(display.width.to_f, display.height.to_f) end redef fun frame_core(display) do - var screen = self.screen - if screen != null then - screen.game.do_turn - screen.do_frame(display) + var game = game + if game != null then + game.do_turn + game.draw(display, assets) end end redef fun input(ie) - do - if ie isa QuitEvent then + do + if paused then return false + if ie isa QuitEvent then quit = true return true end - if screen != null then - return screen.input(ie) + var game = game + if game != null then + return game.input(ie) + end + return false + end +end + +redef class Ball + + redef fun intercepts(event) + do + if event isa ASensorAccelerometer then + acceleration(event.x, event.y) + else if event isa ASensorMagneticField then + #deal with Magnetic field sensor + #print "ASensorMagneticField : x = " + event.x.to_s + " y = " + event.y.to_s + " z = " + event.z.to_s + else if event isa ASensorGyroscope then + #deal with Gyroscope sensor + #print "ASensorGyroscope : x = " + event.x.to_s + " y = " + event.y.to_s + " z = " + event.z.to_s + else if event isa ASensorLight then + #deal with light sensor + #print "ASensorLight : light = " + event.light.to_s + else if event isa ASensorProximity then + #deal with proximity sensor + #print "ASensorProximity : distance = " + event.distance.to_s + else if event isa MotionEvent then + end + return true + end +end + + +redef class Game + + redef fun input(ie) + do + if ie isa ASensorAccelerometer or ie isa MotionEvent then + ball.intercepts(ie) + return true end return false end diff --git a/examples/mnit_ballz/src/ballz_linux.nit b/examples/mnit_ballz/src/ballz_linux.nit new file mode 100644 index 0000000..6f089a8 --- /dev/null +++ b/examples/mnit_ballz/src/ballz_linux.nit @@ -0,0 +1,104 @@ +# this file is part of NIT ( http://www.nitlanguage.org ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Linux part of mnit_ballz +module ballz_linux + +import mnit::linux +import display + + +redef class App + + private var up_arrow_down = false + private var down_arrow_down = false + private var left_arrow_down = false + private var right_arrow_down = false + private var game: nullable Game is noautoinit + + redef fun run + do + maximum_fps = 50 + super + end + + redef fun on_create + do + super + game = new Game(display.width.to_f, display.height.to_f) + end + + redef fun frame_core(display) + do + if up_arrow_down then input(new SDLKeyEvent("up", true)) + if down_arrow_down then input(new SDLKeyEvent("down", true)) + if left_arrow_down then input(new SDLKeyEvent("left", true)) + if right_arrow_down then input(new SDLKeyEvent("right", true)) + + var game = game + if game != null then + game.do_turn + game.draw(display, assets) + end + end + + redef fun input(ie) + do + if ie isa QuitEvent then + quit = true + return true + end + var game = game + if game != null then + return game.input(ie) + end + return false + end +end + +redef class Ball + + redef fun intercepts(event) + do + var value = 5.0 + if event isa SDLKeyEvent then + if event.is_arrow_left then + acceleration(value, 0.0) + app.left_arrow_down = event.is_down + end + if event.is_arrow_right then + acceleration(-value, 0.0) + app.right_arrow_down = event.is_down + end + if event.is_arrow_up then + acceleration(0.0, -value) + app.up_arrow_down = event.is_down + end + if event.is_arrow_down then + acceleration(0.0, value) + app.down_arrow_down = event.is_down + end + end + return false + end +end + +redef class Game + + redef fun input(ie) + do + ball.intercepts(ie) + return false + end +end diff --git a/examples/mnit_ballz/src/collision.nit b/examples/mnit_ballz/src/collision.nit new file mode 100644 index 0000000..825cedc --- /dev/null +++ b/examples/mnit_ballz/src/collision.nit @@ -0,0 +1,87 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Geometric computations around vectors and points for collision detection +module collision + +import geometry + +# trigonometry + +# Get the distance between `p1` and `p2` +fun distance(p1, p2: Point[Float]): Float +do + var x = p1.x - p2.x + var y = p1.y - p2.y + return ( x * x + y * y ).sqrt +end + +# Get the magnitude (length) of `vector` +fun magnitude(vector: Point[Float]): Float do return ( vector.x * vector.x + vector.y * vector.y ).sqrt + +# Get the unit vector of `vector` +fun unit_vector(vector: Point[Float]): Point[Float] do return new Point[Float](vector.x / magnitude(vector), vector.y / magnitude(vector)) + +# Get the dot product of vectors `v1` and `v2` +fun dot_product(v1, v2: Point[Float]): Float do return v1.x * v2.x + v1.y * v2.y + +# Get the vector between `start_point` and `end_point` +fun vector_between(start_point, end_point: Point[Float]): Point[Float] do return new Point[Float](end_point.x - start_point.x, end_point.y - start_point.y) + +# Returns the point on a line with endpoints `l1` and `l2` closest to `center` +fun point_closest_to_line(center, l1, l2: Point[Float]): Point[Float] +do + var luvector = unit_vector(vector_between(l1, l2)) + var l_to_ball = vector_between(l1, center) + + var projection = dot_product(l_to_ball, luvector) + + if projection <= 0.0 then return l1 + if projection >= distance(l1, l2) then return l2 + return new Point[Float](l1.x + luvector.x * projection, l1.y + luvector.y * projection) +end + +# Is the ball with the `center` and `radius` intersecting the line with the endpoints `l1` and `l2`? +fun is_intersecting(center, l1, l2: Point[Float], radius: Float): Bool +do + var closest = point_closest_to_line(center, l1, l2) + var distance = distance(center, closest) + return distance < radius +end + +# Bouncing function, returns the new point of the center of the ball +fun bounce(center, l1, l2, offset: Point[Float]): Point[Float] +do + var bln = bounce_line_normal(center, l1, l2) + var dot = dot_product(offset, bln) + return new Point[Float](offset.x - (2.0 * dot * bln.x), offset.y - (2.0 * dot * bln.y)) +end + +private fun bounce_line_normal(center, l1, l2: Point[Float]): Point[Float] +do + var p = point_closest_to_line(center, l1, l2) + var v = vector_between(p, center) + return unit_vector(v) +end + +# Rotate `p` around `center` through `angle` +fun rotate_point(p, center: Point[Float], angle: Float): Point[Float] +do + var s = angle.sin + var c = angle.cos + + var nx = c * (p.x - center.x) - s * (p.y - center.y) + center.x + var ny = s * (p.x - center.x) + c * (p.y - center.y) + center.y + return new Point[Float](nx, ny) +end diff --git a/examples/mnit_ballz/src/display.nit b/examples/mnit_ballz/src/display.nit new file mode 100644 index 0000000..1d63189 --- /dev/null +++ b/examples/mnit_ballz/src/display.nit @@ -0,0 +1,47 @@ +# this file is part of NIT ( http://www.nitlanguage.org ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Handles the drawing of all the game +module display + +import game_logic + +redef class Ball + + # Draw `self` onto `display` with image from `assets` + fun draw(display: Display, assets: Assets) + do + display.blit_centered(assets.ball, center.x, center.y) + end +end + +redef class Wall + + # Draw `self` onto `display` with image from `assets` + fun draw(display: Display, assets: Assets) + do + display.blit_rotated(assets.vertical_wall, center.x, center.y, angle) + end +end + +redef class Game + + # Draw all the entities onto `display` + fun draw(display: Display, assets: Assets) + do + display.clear (0.0, 0.0, 0.0) + ball.draw(display, assets) + for wall in walls do wall.draw(display, assets) + end +end diff --git a/examples/mnit_ballz/src/game_logic.nit b/examples/mnit_ballz/src/game_logic.nit index 7ece167..38d7682 100644 --- a/examples/mnit_ballz/src/game_logic.nit +++ b/examples/mnit_ballz/src/game_logic.nit @@ -1,7 +1,5 @@ #this file is part of NIT ( http://www.nitlanguage.org ). # -# Copyright 2014 Romain Chanoir -# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at @@ -14,167 +12,172 @@ # See the License for the specific language governing permissions and # limitations under the License. +# All the logic of the game module game_logic -import mnit::android -import android::sensors +import assets +import objects +import geometry::quadtree +import collision -class Ball - var x: Float - var y: Float - var dim: Int - var walls_activated: Bool - var offset_x = 0.0 - var offset_y = 0.0 - var going_left: Bool - var going_down: Bool +redef class Ball - var game: Game + # Scale for drawing the image of `self` + var scale = 1.0 - init(game: Game, x,y: Float, walls: Bool) - do - self.x = x - self.y = y - self.dim = 20 - self.game = game - self.walls_activated = walls - end + # ASensorProximity value for modifying `scale` + # Not used yet + var scale_proximity_modifier = 6.0 + + # Radius of `self` + var radius = 32.0 + + # Movement vector of `self` + var offset = new Point[Float](0.0, 0.0) - # not very useful at this time - fun do_turn + # Calculates the acceleration of `self` + fun acceleration(x,y: Float) do + var max_offset = 10.0 + var max_value = 9.80 + var offset_x = offset.x - x/max_value + var offset_y = offset.y + y/max_value + if offset_x > max_offset then offset_x = max_offset + if offset_x < -max_offset then offset_x = -max_offset + if offset_y > max_offset then offset_y = max_offset + if offset_y < -max_offset then offset_y = -max_offset + offset = new Point[Float](offset_x, offset_y) end - fun intercepts(event: InputEvent): Bool + # Do the collision detection, then move `self`consequently + fun do_turn(game: Game) do - if event isa ASensorAccelerometer then - do_move(event) - else if event isa ASensorMagneticField then - #deal with Magnetic field sensor - print "ASensorMagneticField : x = " + event.x.to_s + " y = " + event.y.to_s + " z = " + event.z.to_s - else if event isa ASensorGyroscope then - #deal with Gyroscope sensor - print "ASensorGyroscope : x = " + event.x.to_s + " y = " + event.y.to_s + " z = " + event.z.to_s - else if event isa ASensorLight then - #deal with light sensor - print "ASensorLight : light = " + event.light.to_s - else if event isa ASensorProximity then - #deal with proximity sensor - print "ASensorProximity : distance = " + event.distance.to_s - else if event isa MotionEvent then - activate_walls(event) + offset = new Point[Float](offset.x * 0.98, offset.y * 0.98) + var np = collision(game.quadtree) + if np != null then + offset = np + center = new Point[Float](center.x + offset.x, center.y + offset.y) + else + center = new Point[Float](center.x + offset.x, center.y + offset.y) end - return true end - fun do_move (event: ASensorAccelerometer) + # Collision detection + fun collision(quadtree: SQuadTree[OrientedLine]): nullable Point[Float] do - # acceleration value - var vx = event.x - var vy = event.y - var gw = game.width - var gh = game.height - - # acceleration - var max_value = 9.80 - var acceleration_x = vx/max_value - var acceleration_y = vy/max_value - offset_x -= (acceleration_x/10.0)*(vx.abs) + offset_x/125.0 - offset_y += (acceleration_y/10.0)*(vy.abs) - offset_y/125.0 - var nx = self.x + offset_x - var ny = self.y + offset_y - going_left = offset_x > 0.0 - going_down = offset_y > 0.0 - - # x value - if nx >= 0.0 and nx <= gw then - self.x = nx - else if nx < 0.0 then - if not walls_activated then self.x = gw else do_bounce(1) - else if nx > gw then - if not walls_activated then self.x = 0.0 else do_bounce(1) + var nx = self.center.x + offset.x + var ny = self.center.y + offset.y + var new_center = new Point[Float](nx, ny) + var effective_radius = radius*scale + # Lines intersecting with the ball + var intersecting_lines = new Array[OrientedLine] + + # Line intersecting closest to the ball + var intersecting_line: nullable OrientedLine = null + + # closest point of the intersecting line + var closest_point: nullable Point[Float] = null + + # get the intersecting lines with help of the quadtree + var lines = quadtree.items_overlapping(new_center.padded(effective_radius)) + for l in lines do + if is_intersecting(new_center, l.point_left, l.point_right, effective_radius) then + intersecting_lines.add(l) + end end - # y value - if ny >= 0.0 and ny <= gh then - self.y = ny - else if ny < 0.0 then - if not walls_activated then self.y = gh else do_bounce(2) - else if ny > gh then - if not walls_activated then self.y = 0.0 else do_bounce(2) + # get the line closest to the ball from the intersecting lines, setting the closest point + var min_dist = 100.0 + if intersecting_lines.length >= 2 then + for l in intersecting_lines do + var closest = point_closest_to_line(new_center, l.point_left, l.point_right) + var distance = distance(closest, new_center) + if distance < min_dist then + min_dist = distance + intersecting_line = l + closest_point = closest + end + end + else if intersecting_lines.length == 1 then + intersecting_line = intersecting_lines[0] + closest_point = point_closest_to_line(new_center, intersecting_line.point_left, intersecting_line.point_right) end - end - # bounce in function of the position of the wall relative to the ball: 1=left or right, 2=top or down - fun do_bounce(wall_position: Int) - do - if wall_position == 1 then - offset_x = -offset_x*0.85 - else if wall_position == 2 then - offset_y = -offset_y*0.85 - end - if offset_x.abs > 1.0 and offset_y.abs > 1.0 then - self.x += offset_x - self.y += offset_y + if intersecting_line != null and closest_point != null then + return bounce(center, intersecting_line.point_left, intersecting_line.point_right, offset) end + return null end - fun activate_walls(event: MotionEvent) - do - if event.just_went_down then - walls_activated = not walls_activated - end - end + # Event interception + fun intercepts(event: InputEvent): Bool is abstract end -class Screen - var ball_img: Image - var game: Game - - init(app: App, display: Display) - do - game = new Game(display) - ball_img = app.load_asset("images/ball.png").as(Image) - var scale = game.img_dim.to_f / game.img_ori_dim.to_f - ball_img.scale = scale - ball_img.scale = 3.0 - end +# The core of the game +class Game - fun do_frame(display: Display) - do - display.clear(0.0, 0.0, 0.0) - display.blit_rotated(ball_img, game.ball.x, game.ball.y, 0.0) - end + # The Ball! + var ball: Ball is noinit - fun input(ie: InputEvent): Bool - do - if ie isa ASensorProximity then - if ie.distance == 0.0 then ball_img.scale = 6.0 else ball_img.scale = 3.0 - else - game.ball.intercepts(ie) - end - return true - end -end + # List of walls in the level + var walls: Array[Wall] is noinit -class Game - var ball: Ball + # Width of the display var width: Float + + # Heightof the display var height: Float - var img_ori_dim: Int = 256 - fun img_dim: Int do return 210 + # Quadtree used for collision detection + var quadtree: SQuadTree[OrientedLine] is noinit - init(display: Display) + init do - width = display.width.to_f - height = display.height.to_f - ball = new Ball(self, width/2.0, height/2.0, false) + ball = new Ball(new Point[Float](width/2.0, height/2.0)) + # Walls initialisation + var walla = new Wall(new Point[Float](width/4.0, height/4.0), pi/3.0, 1.0) + var wallb = new Wall(new Point[Float](width*0.75, height/4.0), 0.0, 1.0) + var wallc = new Wall(new Point[Float](width/4.0, height*0.75), 0.0, 1.0) + var walld = new Wall(new Point[Float](width*0.75, height*0.75), pi/3.0, 1.0) + walls = new Array[Wall].with_items(walla, wallb, wallc, walld) + + # adding screen bordures + var i = new Point[Float](0.0,0.0) + var a = new Point[Float](0.0, height/2.0) + var b = new Point[Float](width/2.0, 0.0) + var c = new Point[Float](width, height/2.0) + var d = new Point[Float](width/2.0, height) + + var l1 = new OrientedLine(i, i, pi/2.0, height, a) + var l2 = new OrientedLine(i, i, 0.0, width, b) + var l3 = new OrientedLine(i, i, pi/2.0, height, c) + var l4 = new OrientedLine(i, i, 0.0, width, d) + + quadtree = new SQuadTree[OrientedLine](5, width, height) + for w in walls do for l in w.lines do + quadtree.add(l) + end + quadtree.add(l1) + quadtree.add(l2) + quadtree.add(l3) + quadtree.add(l4) end - fun do_turn - do - ball.do_turn + # Only calls `do_turn` of the ball for the moment + fun do_turn do ball.do_turn(self) + + # Input gestion + fun input(ie: InputEvent): Bool do return false +end + +redef class App + + # Assets used in all the app + var assets = new Assets + + redef fun on_create do + super + assets.load end end diff --git a/examples/mnit_ballz/src/objects.nit b/examples/mnit_ballz/src/objects.nit new file mode 100644 index 0000000..d8e1686 --- /dev/null +++ b/examples/mnit_ballz/src/objects.nit @@ -0,0 +1,100 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Module containing all objects of the game +module objects + +import geometry +import geometry::polygon +import geometry::boxes +import collision + +# The ball is the main character of the game! +class Ball + # Center of the ball + var center: Point[Float] is writable +end + +# Walls make the ball bounce on them +class Wall + # Coordinates of the center of the wall + var center: Point[Float] + + # Angle in radian + var angle: Float + + # Scale for drawing `self` + var scale: Float + + # Width of `self` + var width: Float is noautoinit + + # Height of `self` + var height: Float is noautoinit + + # Lines composing `self` + var lines: Array[OrientedLine] is noautoinit + + # Initialize `self` with all its lines from `center` and `angle` + init do + self.height = 128.0 + self.width = 32.0 + var i = new Point[Float](0.0, 0.0) + var j = new Point[Float](0.0, 0.0) + + var a = new Point[Float]((center.x - width/2.0), center.y) + var b = new Point[Float]((center.x), (center.y - height/2.0)) + var c = new Point[Float]((center.x + width/2.0), center.y) + var d = new Point[Float]((center.x), (center.y + height/2.0)) + + var l1 = new OrientedLine(i, j, angle - pi/2.0, height * scale.to_f, rotate_point(a, center, angle)) + var l2 = new OrientedLine(i, j, angle, width * scale.to_f, rotate_point(b, center, angle)) + var l3 = new OrientedLine(i, j, angle - pi/2.0, height * scale.to_f, rotate_point(c, center, angle)) + var l4 = new OrientedLine(i, j, angle, width * scale.to_f, rotate_point(d, center, angle)) + lines = new Array[OrientedLine] + lines.add_all([l1, l2, l3, l4]) + end +end + +# A line represented with a center and an angle +class OrientedLine + super Line[Float] + redef type P: Point[Float] + + # Angle in radian + var angle: Float is writable + + # Length + var length: Float + + # Center + var center: Point[Float] + + redef fun point_left + do + var luv = unit_vector(new Point[Float](angle.cos, angle.sin)) + var offset_from_center = new Point[Float](luv.x * (length / 2.0), luv.y * (length / 2.0)) + return new Point[Float](center.x + offset_from_center.x, center.y + offset_from_center.y) + end + + redef fun point_right + do + var luv = unit_vector(new Point[Float](angle.cos, angle.sin)) + var offset_from_center = new Point[Float](luv.x * length / 2.0, luv.y * length / 2.0) + return new Point[Float](center.x - offset_from_center.x, center.y - offset_from_center.y) + end + + redef fun left do return point_left.x.min(point_right.x) + redef fun right do return point_left.x.max(point_right.x) +end diff --git a/examples/mnit_dino/Makefile b/examples/mnit_dino/Makefile index 42364bf..14faa98 100644 --- a/examples/mnit_dino/Makefile +++ b/examples/mnit_dino/Makefile @@ -8,6 +8,10 @@ android: android-icons mkdir -p bin ../../bin/nitc -o bin/dino.apk src/dino_android.nit +android-release: android-icons + mkdir -p bin + ../../bin/nitc -o bin/dino.apk src/dino_android.nit --release + ../../contrib/inkscape_tools/bin/svg_to_icons: $(MAKE) -C ../../contrib/inkscape_tools diff --git a/examples/mnit_dino/project.ini b/examples/mnit_dino/package.ini similarity index 97% rename from examples/mnit_dino/project.ini rename to examples/mnit_dino/package.ini index a4a5c6c..fbd7d4f 100644 --- a/examples/mnit_dino/project.ini +++ b/examples/mnit_dino/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=mnit_dino tags=game maintainer=Alexis Laferrière diff --git a/examples/montecarlo.ini b/examples/montecarlo.ini index d789aa4..30f7263 100644 --- a/examples/montecarlo.ini +++ b/examples/montecarlo.ini @@ -1,4 +1,4 @@ -[project] +[package] name=montecarlo tags=example maintainer=Jean Privat diff --git a/lib/projects.ini b/examples/packages.ini similarity index 100% rename from lib/projects.ini rename to examples/packages.ini diff --git a/examples/print_arguments.ini b/examples/print_arguments.ini index 888fd2b..3ca7f26 100644 --- a/examples/print_arguments.ini +++ b/examples/print_arguments.ini @@ -1,4 +1,4 @@ -[project] +[package] name=print_arguments tags=example maintainer=Jean Privat diff --git a/examples/procedural_array.ini b/examples/procedural_array.ini index 90e31a7..cf32ba0 100644 --- a/examples/procedural_array.ini +++ b/examples/procedural_array.ini @@ -1,4 +1,4 @@ -[project] +[package] name=procedural_array tags=example maintainer=Jean Privat diff --git a/examples/rosettacode/project.ini b/examples/rosettacode/package.ini similarity index 97% rename from examples/rosettacode/project.ini rename to examples/rosettacode/package.ini index 3452885..523694e 100644 --- a/examples/rosettacode/project.ini +++ b/examples/rosettacode/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=rosettacode tags=example maintainer=Jean Privat diff --git a/examples/shoot/Makefile b/examples/shoot/Makefile index 5e564d7..a42ffde 100644 --- a/examples/shoot/Makefile +++ b/examples/shoot/Makefile @@ -8,6 +8,10 @@ android: mkdir -p bin ../../bin/nitc -o bin/shoot.apk src/shoot_android.nit +android-release: + mkdir -p bin + ../../bin/nitc -o bin/shoot.apk src/shoot_android.nit --release + null: mkdir -p bin ../../bin/nitc -o bin/shoot_null src/shoot_null.nit diff --git a/examples/shoot/project.ini b/examples/shoot/package.ini similarity index 96% rename from examples/shoot/project.ini rename to examples/shoot/package.ini index a2ea7c3..0fe112a 100644 --- a/examples/shoot/project.ini +++ b/examples/shoot/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=shoot tags=game maintainer=Jean Privat diff --git a/lib/a_star.ini b/lib/a_star.ini index 64e1f61..5ec2a3d 100644 --- a/lib/a_star.ini +++ b/lib/a_star.ini @@ -1,4 +1,4 @@ -[project] +[package] name=a_star tags=algo,lib maintainer=Alexis Laferrière diff --git a/lib/ai/project.ini b/lib/ai/package.ini similarity index 96% rename from lib/ai/project.ini rename to lib/ai/package.ini index cff8fc6..3e9fdf8 100644 --- a/lib/ai/project.ini +++ b/lib/ai/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=ai tags=ai,algo,lib maintainer=Jean Privat diff --git a/lib/android/audio.nit b/lib/android/audio.nit index c70dd40..b361b4f 100644 --- a/lib/android/audio.nit +++ b/lib/android/audio.nit @@ -138,7 +138,6 @@ private extern class NativeMediaPlayer in "Java" `{ android.media.MediaPlayer `} self.setDataSource(fd, start_offset, length); return 1; }catch(Exception e) { - Log.e("Error loading the Media Player with a file descriptor", e.getMessage()); return 0; } `} @@ -483,7 +482,7 @@ class MediaPlayer end redef class PlayableAudio - redef init do app.add_to_sounds(self) + redef init do add_to_sounds(self) end redef class Sound @@ -537,8 +536,8 @@ redef class Sound end redef fun play do - if self.error != null then return if not is_loaded then load + if self.error != null then return soundpool.play(soundpool_id) end @@ -599,8 +598,8 @@ redef class Music end redef fun play do - if self.error != null then return if not is_loaded then load + if self.error != null then return media_player.start end @@ -617,9 +616,6 @@ end redef class App - # Sounds handled by the application, when you load a sound, it's added to this list. - # This array is used in `pause` and `resume` - private var sounds = new Array[PlayableAudio] # Returns the default MediaPlayer of the application. # When you load a music, it goes in this MediaPlayer. @@ -676,12 +672,6 @@ redef class App return add_to_sounds(default_mediaplayer.load_sound(resource_manager.raw_id(music), self.native_activity)).as(Music) end - # Factorizes `sounds.add` to use it in `load_music`, `load_sound`, `load_music_from_res` and `load_sound_from_res` - private fun add_to_sounds(sound: PlayableAudio): PlayableAudio do - sounds.add(sound) - return sound - end - redef fun on_pause do super for s in sounds do s.pause @@ -700,3 +690,16 @@ redef class App for s in sounds do s.resume end end + +redef class Sys + + # Sounds handled by the application, when you load a sound, it's added to this list. + # This array is used in `pause` and `resume` + private var sounds = new Array[PlayableAudio] + + # Factorizes `sounds.add` to use it in `load_music`, `load_sound`, `load_music_from_res` and `load_sound_from_res` + private fun add_to_sounds(sound: PlayableAudio): PlayableAudio do + sounds.add(sound) + return sound + end +end diff --git a/lib/android/native_app_glue.nit b/lib/android/native_app_glue.nit index 2202827..d99f5a9 100644 --- a/lib/android/native_app_glue.nit +++ b/lib/android/native_app_glue.nit @@ -368,4 +368,13 @@ end # Android NDK's structure to control the native window for drawing extern class ANativeWindow `{ ANativeWindow* `} + # Change the format and size of the window buffers + # + # All arguments can be set to 0 to use the default devices values. + # `width` and `height` must both be set to 0 or have significant values. + # + # `format` is a value specified by EGL. + fun set_buffers_geometry(width, height, format: Int): Bool `{ + return ANativeWindow_setBuffersGeometry(self, (int32_t)width, (int32_t)height, (int32_t)format); + `} end diff --git a/lib/android/project.ini b/lib/android/package.ini similarity index 96% rename from lib/android/project.ini rename to lib/android/package.ini index d378b05..6912264 100644 --- a/lib/android/project.ini +++ b/lib/android/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=android tags=platform,lib maintainer=Alexis Laferrière diff --git a/lib/android/sensors.nit b/lib/android/sensors.nit index 3ee9765..b969389 100644 --- a/lib/android/sensors.nit +++ b/lib/android/sensors.nit @@ -20,19 +20,19 @@ # # ~~~~nitish # #FIXME rewrite the example -# var app = new MyApp -# app.sensors_support_enabled = true -# app.accelerometer.enabled = true -# app.accelerometer.eventrate = 10000 -# app.magnetic_field.enabled = true -# app.gyroscope.enabled = true -# app.light.enabled = true -# app.proximity.enabled = true -# app.main_loop +# redef class App +# sensors_support_enabled = true +# accelerometer.enabled = true +# accelerometer.eventrate = 10000 +# magnetic_field.enabled = true +# gyroscope.enabled = true +# light.enabled = true +# proximity.enabled = true +# end # ~~~~ # -# In this example, we enable the sensor support, then enable all types of sensors supported, before running the app. -# The result is you get all type of SensorEvent (ASensorAccelerometer, ASensorMagneticField ...) in the input method of your app +# In this example, we enable the sensor support, then enable all types of sensors supported by the API, directly with `App` attributes +# As a result, you get all type of SensorEvent (ASensorAccelerometer, ASensorMagneticField ...) in the `input` callback of `App` module sensors import android @@ -270,8 +270,8 @@ redef class App private fun enable_accelerometer do accelerometer.asensor = sensormanager.get_default_sensor(new ASensorType.accelerometer) - if accelerometer.asensor.address_is_null then - print "Accelerometer sensor unavailable" + if accelerometer.asensor.address_is_null then + print "Accelerometer sensor unavailable" else if eventqueue.enable_sensor(accelerometer.asensor) < 0 then print "Accelerometer enabling failed" eventqueue.set_event_rate(accelerometer.asensor, accelerometer.event_rate) @@ -314,7 +314,7 @@ redef class App private fun enable_proximity do proximity.asensor = sensormanager.get_default_sensor(new ASensorType.proximity) - if proximity.asensor.address_is_null then + if proximity.asensor.address_is_null then print "Proximity sensor unavailable" else if eventqueue.enable_sensor(proximity.asensor) < 0 then print "Proximity enabling failed" diff --git a/lib/app/project.ini b/lib/app/package.ini similarity index 96% rename from lib/app/project.ini rename to lib/app/package.ini index 7032d20..d5c48c1 100644 --- a/lib/app/project.ini +++ b/lib/app/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=app tags=lib maintainer=Alexis Laferrière diff --git a/lib/array_debug.ini b/lib/array_debug.ini index 8317cf9..467aeae 100644 --- a/lib/array_debug.ini +++ b/lib/array_debug.ini @@ -1,4 +1,4 @@ -[project] +[package] name=array_debug tags=debug,lib maintainer=Alexandre Terrasa diff --git a/lib/base64.ini b/lib/base64.ini index 629c07b..7009786 100644 --- a/lib/base64.ini +++ b/lib/base64.ini @@ -1,4 +1,4 @@ -[project] +[package] name=base64 tags=encoding,lib maintainer=Lucas Bajolet diff --git a/lib/bcm2835/project.ini b/lib/bcm2835/package.ini similarity index 96% rename from lib/bcm2835/project.ini rename to lib/bcm2835/package.ini index 07ade4d..928a8e6 100644 --- a/lib/bcm2835/project.ini +++ b/lib/bcm2835/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=bcm2835 tags=embedded,lib maintainer=Alexis Laferrière diff --git a/lib/binary/project.ini b/lib/binary/package.ini similarity index 96% rename from lib/binary/project.ini rename to lib/binary/package.ini index c9f47da..227e529 100644 --- a/lib/binary/project.ini +++ b/lib/binary/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=binary tags=io,lib maintainer=Alexis Laferrière diff --git a/lib/bitmap/project.ini b/lib/bitmap/package.ini similarity index 96% rename from lib/bitmap/project.ini rename to lib/bitmap/package.ini index 54ff7c2..21ecf9a 100644 --- a/lib/bitmap/project.ini +++ b/lib/bitmap/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=bitmap tags=lib maintainer=Lucas Bajolet diff --git a/lib/bucketed_game.ini b/lib/bucketed_game.ini index b419878..4824079 100644 --- a/lib/bucketed_game.ini +++ b/lib/bucketed_game.ini @@ -1,4 +1,4 @@ -[project] +[package] name=bucketed_game tags=game,lib maintainer=Alexis Laferrière diff --git a/lib/buffered_ropes.ini b/lib/buffered_ropes.ini index b221516..280bea6 100644 --- a/lib/buffered_ropes.ini +++ b/lib/buffered_ropes.ini @@ -1,4 +1,4 @@ -[project] +[package] name=buffered_ropes tags=algo,text,lib maintainer=Lucas Bajolet diff --git a/lib/c.ini b/lib/c.ini index 415a61b..22850fc 100644 --- a/lib/c.ini +++ b/lib/c.ini @@ -1,4 +1,4 @@ -[project] +[package] name=c tags=language,wrapper,lib maintainer=Alexis Laferrière diff --git a/lib/c.nit b/lib/c.nit index deb6765..a9b04e1 100644 --- a/lib/c.nit +++ b/lib/c.nit @@ -93,8 +93,8 @@ class CIntArray super size end - # Build from an `Array[Int]` - new from(array: Array[Int]) + # Create from an `SequenceRead[Int]` + new from(array: SequenceRead[Int]) do var carray = new CIntArray(array.length) for i in array.length.times do @@ -129,7 +129,7 @@ class CByteArray super size end - # Build from a `SequenceRead[Byte]` + # Create from a `SequenceRead[Byte]` new from(array: SequenceRead[Byte]) do var carray = new CByteArray(array.length) @@ -166,8 +166,8 @@ class CNativeStringArray super size end - # Build from an `Array[NativeString]` - new from(array: Array[NativeString]) + # Create from an `SequenceRead[NativeString]` + new from(array: SequenceRead[NativeString]) do var carray = new CNativeStringArray(array.length) for i in array.length.times do diff --git a/lib/cartesian.ini b/lib/cartesian.ini index 7dd61d7..fbdc2c4 100644 --- a/lib/cartesian.ini +++ b/lib/cartesian.ini @@ -1,4 +1,4 @@ -[project] +[package] name=cartesian tags=algo,lib maintainer=Jean Privat diff --git a/lib/cocoa/project.ini b/lib/cocoa/package.ini similarity index 96% rename from lib/cocoa/project.ini rename to lib/cocoa/package.ini index ceee0f1..44c18eb 100644 --- a/lib/cocoa/project.ini +++ b/lib/cocoa/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=cocoa tags=wrapper,lib maintainer=Alexis Laferrière diff --git a/lib/combinations.ini b/lib/combinations.ini index bf0cda4..f97a0ed 100644 --- a/lib/combinations.ini +++ b/lib/combinations.ini @@ -1,4 +1,4 @@ -[project] +[package] name=combinations tags=algo,lib maintainer=Jean Privat diff --git a/lib/console.ini b/lib/console.ini index ba89925..10ec43b 100644 --- a/lib/console.ini +++ b/lib/console.ini @@ -1,4 +1,4 @@ -[project] +[package] name=console tags=terminal,lib maintainer=Jean-Christophe Beaupré diff --git a/lib/core/project.ini b/lib/core/package.ini similarity index 96% rename from lib/core/project.ini rename to lib/core/package.ini index 652d22e..9b4db38 100644 --- a/lib/core/project.ini +++ b/lib/core/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=core tags=lib maintainer=Jean Privat diff --git a/lib/counter.ini b/lib/counter.ini index cde38a3..09bda32 100644 --- a/lib/counter.ini +++ b/lib/counter.ini @@ -1,4 +1,4 @@ -[project] +[package] name=counter tags=algo,lib maintainer=Jean Privat diff --git a/lib/cpp.ini b/lib/cpp.ini index 7839cf6..a317f35 100644 --- a/lib/cpp.ini +++ b/lib/cpp.ini @@ -1,4 +1,4 @@ -[project] +[package] name=cpp tags=language,wrapper,lib maintainer=Alexis Laferrière diff --git a/lib/crypto.ini b/lib/crypto.ini index 6487e51..e8b4cf1 100644 --- a/lib/crypto.ini +++ b/lib/crypto.ini @@ -1,4 +1,4 @@ -[project] +[package] name=crypto tags=crypto,algo,lib maintainer=Lucas Bajolet diff --git a/lib/csv/project.ini b/lib/csv/package.ini similarity index 96% rename from lib/csv/project.ini rename to lib/csv/package.ini index b8008e0..abbb852 100644 --- a/lib/csv/project.ini +++ b/lib/csv/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=csv tags=format,lib maintainer=Alexandre Terrasa diff --git a/lib/curl/project.ini b/lib/curl/package.ini similarity index 96% rename from lib/curl/project.ini rename to lib/curl/package.ini index d399756..bc8502d 100644 --- a/lib/curl/project.ini +++ b/lib/curl/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=curl tags=network,wrapper,lib maintainer=Alexis Laferrière diff --git a/lib/curses/project.ini b/lib/curses/package.ini similarity index 96% rename from lib/curses/project.ini rename to lib/curses/package.ini index 58813c5..cd3c99e 100644 --- a/lib/curses/project.ini +++ b/lib/curses/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=curses tags=ui,terminal,wrapper,lib maintainer=Jean Privat diff --git a/lib/date.ini b/lib/date.ini index 148d496..ac74d2d 100644 --- a/lib/date.ini +++ b/lib/date.ini @@ -1,4 +1,4 @@ -[project] +[package] name=date tags=lib maintainer=Mehdi Ait Younes diff --git a/lib/deriving.ini b/lib/deriving.ini index a9205b6..44690f8 100644 --- a/lib/deriving.ini +++ b/lib/deriving.ini @@ -1,4 +1,4 @@ -[project] +[package] name=deriving tags=lib maintainer=Jean Privat diff --git a/lib/dom/project.ini b/lib/dom/package.ini similarity index 96% rename from lib/dom/project.ini rename to lib/dom/package.ini index 7b5938c..64a1947 100644 --- a/lib/dom/project.ini +++ b/lib/dom/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=dom tags=xml,lib maintainer=Lucas Bajolet diff --git a/lib/dummy_array.ini b/lib/dummy_array.ini index b4db4f7..cc510fc 100644 --- a/lib/dummy_array.ini +++ b/lib/dummy_array.ini @@ -1,4 +1,4 @@ -[project] +[package] name=dummy_array tags=algo,lib maintainer=Floréal Morandat diff --git a/lib/egl.ini b/lib/egl.ini index b3bb784..c77b5f8 100644 --- a/lib/egl.ini +++ b/lib/egl.ini @@ -1,4 +1,4 @@ -[project] +[package] name=egl tags=graphics,wrapper,lib maintainer=Alexis Laferrière diff --git a/lib/egl.nit b/lib/egl.nit index 8934b7e..69df8e5 100644 --- a/lib/egl.nit +++ b/lib/egl.nit @@ -454,3 +454,6 @@ end fun egl_bind_opengl_api: Bool `{ return eglBindAPI(EGL_OPENGL_API); `} fun egl_bind_opengl_es_api: Bool `{ return eglBindAPI(EGL_OPENGL_ES_API); `} fun egl_bind_openvg_api: Bool `{ return eglBindAPI(EGL_OPENVG_API); `} + +# Handle to the default display to use with EGL +fun egl_default_display: Pointer `{ return EGL_DEFAULT_DISPLAY; `} diff --git a/lib/emscripten/project.ini b/lib/emscripten/package.ini similarity index 97% rename from lib/emscripten/project.ini rename to lib/emscripten/package.ini index 9789637..458a8bc 100644 --- a/lib/emscripten/project.ini +++ b/lib/emscripten/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=emscripten tags=platform,lib maintainer=Alexis Laferrière diff --git a/lib/filter_stream.ini b/lib/filter_stream.ini index 5ba5b32..c279e04 100644 --- a/lib/filter_stream.ini +++ b/lib/filter_stream.ini @@ -1,4 +1,4 @@ -[project] +[package] name=filter_stream tags=io,lib maintainer=Floréal Morandat diff --git a/lib/for_abuse.ini b/lib/for_abuse.ini index c88d7e9..2b768d4 100644 --- a/lib/for_abuse.ini +++ b/lib/for_abuse.ini @@ -1,4 +1,4 @@ -[project] +[package] name=for_abuse tags=algo,lib maintainer=Jean Privat diff --git a/lib/gamnit/display.nit b/lib/gamnit/display.nit new file mode 100644 index 0000000..94ece8a --- /dev/null +++ b/lib/gamnit/display.nit @@ -0,0 +1,49 @@ +# This file is part of NIT (http://www.nitlanguage.org). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Abstract display services +module display + +import ::glesv2 + +import display_linux is conditional(linux) +import display_android is conditional(android) + +# Should Gamnit be more verbose? +fun debug_gamnit: Bool do return false + +# General display class, is sized and drawable +class GamnitDisplay + + # Width of the display, in pixels + fun width: Int is abstract + + # Height of the display, in pixels + fun height: Int is abstract + + # Prepare this display + # + # The implementation varies per platform. + fun setup is abstract + + # Close this display and free underlying resources + # + # The implementation varies per platform. + fun close do end + + # Flip the display buffers + # + # The implementation varies per platform. + fun flip do end +end diff --git a/lib/gamnit/display_android.nit b/lib/gamnit/display_android.nit new file mode 100644 index 0000000..d0e5235 --- /dev/null +++ b/lib/gamnit/display_android.nit @@ -0,0 +1,47 @@ +# This file is part of NIT (http://www.nitlanguage.org). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Gamnit display implementation for Android +# +# Generated APK files require OpenGL ES 2.0. +# +# This modules uses `android::native_app_glue` and the Android NDK. +module display_android is + android_manifest """""" +end + +import ::android + +private import gamnit::egl + +redef class GamnitDisplay + + redef fun setup + do + var native_display = egl_default_display + var native_window = app.native_app_glue.window + + setup_egl_display native_display + + # We need 8 bits per color for selection by color + select_egl_config(8, 8, 8, 0, 8, 0, 0) + + var format = egl_config.attribs(egl_display).native_visual_id + native_window.set_buffers_geometry(0, 0, format) + + setup_egl_context native_window + end + + redef fun close do close_egl +end diff --git a/lib/gamnit/display_linux.nit b/lib/gamnit/display_linux.nit new file mode 100644 index 0000000..109ff51 --- /dev/null +++ b/lib/gamnit/display_linux.nit @@ -0,0 +1,91 @@ +# This file is part of NIT (http://www.nitlanguage.org). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Gamnit display implementation for GNU/Linux using `egl`, `sdl` and `x11` +module display_linux + +import sdl +import x11 + +import egl # local to gamnit +import display + +redef class GamnitDisplay + + # Actual width or desired width of the window, can be set before calling `setup` + fun width=(value: Int) do requested_width = value + private var requested_width = 1920 + + # Actual height or desired height of the window, can be set before calling `setup` + fun height=(value: Int) do requested_height = value + private var requested_height = 1080 + + # Setup SDL, X11, EGL in order + redef fun setup + do + if debug_gamnit then print "Setting up SDL" + self.sdl_display = setup_sdl(requested_width, requested_height) + + if debug_gamnit then print "Setting up X11" + var x11_display = setup_x11 + var window_handle = window_handle + setup_egl_display x11_display + + if debug_gamnit then print "Setting up EGL context" + select_egl_config(8, 8, 8, 8, 8, 0, 0) + setup_egl_context window_handle + end + + # Close EGL and SDL in reverse order of `setup` (nothing to do for X11) + redef fun close + do + close_egl + close_sdl + end + + # --- + # SDL + + # The SDL display managing the window and events + var sdl_display: SDLDisplay is noautoinit + + # Setup the SDL display and lib + fun setup_sdl(window_width, window_height: Int): SDLDisplay + do + var sdl_display = new SDLDisplay(window_width, window_height) + assert not sdl_display.address_is_null else print "Opening SDL display failed" + return sdl_display + end + + # Close the SDL display + fun close_sdl do sdl_display.destroy + + # Get a native handle to the current SDL window + fun window_handle: Pointer + do + var sdl_wm_info = new SDLSystemWindowManagerInfo + return sdl_wm_info.x11_window_handle + end + + # --- + # X11 + + # Get a native handle to the current X11 display + fun setup_x11: Pointer + do + var x11_display = x_open_default_display + assert not x11_display.address_is_null else print "Opening X11 display failed" + return x11_display + end +end diff --git a/lib/gamnit/egl.nit b/lib/gamnit/egl.nit new file mode 100644 index 0000000..3fcb8c8 --- /dev/null +++ b/lib/gamnit/egl.nit @@ -0,0 +1,115 @@ +# This file is part of NIT (http://www.nitlanguage.org). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Use of EGL to implement Gamnit on GNU/Linux and Android +module egl + +import ::egl + +import gamnit::display + +redef class GamnitDisplay + + # The EGL display + var egl_display: EGLDisplay is noautoinit + + # The EGL context + var egl_context: EGLContext is noautoinit + + # The EGL surface for the window + var window_surface: EGLSurface is noautoinit + + # The selected EGL configuration + var egl_config: EGLConfig is noautoinit + + # Setup the EGL display for the given `x11_display` + protected fun setup_egl_display(x11_display: Pointer) + do + var egl_display = new EGLDisplay(x11_display) + assert egl_display.is_valid else print "new EGL display is not valid" + + egl_display.initialize + assert egl_display.is_valid else print "EGL initialize error: {egl_display.error}" + + self.egl_display = egl_display + end + + # Select an EGL config + protected fun select_egl_config(blue, green, red, alpha, depth, stencil, sample: Int) + do + var config_chooser = new EGLConfigChooser + config_chooser.renderable_type_egl + config_chooser.surface_type_egl + config_chooser.blue_size = blue + config_chooser.green_size = green + config_chooser.red_size = red + if alpha > 0 then config_chooser.alpha_size = alpha + if depth > 0 then config_chooser.depth_size = depth + if stencil > 0 then config_chooser.stencil_size = stencil + if sample > 0 then config_chooser.sample_buffers = sample + config_chooser.close + + var configs = config_chooser.choose(egl_display) + assert configs != null else print "Choosing EGL config failed: {egl_display.error}" + assert not configs.is_empty else print "Found no EGL config" + + if debug_gamnit then + print "EGL available configurations:" + for config in configs do + var attribs = config.attribs(egl_display) + print "* Conformant to: {attribs.conformant}" + print " Caveats: {attribs.caveat}" + print " Size of RGBA: {attribs.red_size} {attribs.green_size} {attribs.blue_size} {attribs.alpha_size}" + print " Buffer, depth, stencil: {attribs.buffer_size} {attribs.depth_size} {attribs.stencil_size}" + end + end + + # We use the first one, it is recommended + self.egl_config = configs.first + end + + # Setup the EGL context for the given `window_handle` + protected fun setup_egl_context(window_handle: Pointer) + do + var window_surface = egl_display.create_window_surface(egl_config, window_handle, [0]) + assert window_surface.is_ok else print "Creating EGL window surface failed: {egl_display.error}" + self.window_surface = window_surface + + egl_context = egl_display.create_context(egl_config) + assert egl_context.is_ok else print "Creating EGL context failed: {egl_display.error}" + + var make_current_res = egl_display.make_current(window_surface, window_surface, egl_context) + assert make_current_res else print "Creating EGL make current failed: {egl_display.error}" + + # TODO make the API selection configurable per platform + assert egl_bind_opengl_es_api else print "EGL bind API failed: {egl_display.error}" + end + + redef fun width do return window_surface.attribs(egl_display).width + + redef fun height do return window_surface.attribs(egl_display).height + + # Close the EGL context + fun close_egl + do + egl_display.make_current(new EGLSurface.none, new EGLSurface.none, new EGLContext.none) + egl_display.destroy_context(egl_context) + egl_display.destroy_surface(window_surface) + end + + redef fun flip + do + egl_display.swap_buffers(window_surface) + end +end diff --git a/lib/gamnit/examples/triangle/Makefile b/lib/gamnit/examples/triangle/Makefile new file mode 100644 index 0000000..22172de --- /dev/null +++ b/lib/gamnit/examples/triangle/Makefile @@ -0,0 +1,21 @@ +NITC=../../../../bin/nitc +NITLS=../../../../bin/nitls + +all: bin/standalone_triangle bin/triangle bin/triangle.apk + +bin/standalone_triangle: $(shell ${NITLS} -M src/standalone_triangle.nit linux) ${NITC} + ${NITC} src/standalone_triangle.nit -m linux -o $@ + +bin/triangle: $(shell ${NITLS} -M src/portable_triangle.nit linux) ${NITC} + ${NITC} src/portable_triangle.nit -m linux -o $@ + +check: bin/standalone_triangle bin/triangle + bin/standalone_triangle + bin/triangle + +android: bin/triangle.apk +bin/triangle.apk: $(shell ${NITLS} -M src/portable_triangle.nit android) ${NITC} res/drawable-hdpi/icon.png + ${NITC} src/portable_triangle.nit -m android -o $@ + +res/drawable-hdpi/icon.png: art/icon.svg + ../../../../contrib/inkscape_tools/bin/svg_to_icons --out res --android art/icon.svg diff --git a/lib/gamnit/examples/triangle/art/icon.svg b/lib/gamnit/examples/triangle/art/icon.svg new file mode 100644 index 0000000..26f7c04 --- /dev/null +++ b/lib/gamnit/examples/triangle/art/icon.svg @@ -0,0 +1,82 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/lib/gamnit/examples/triangle/bin/.gitignore b/lib/gamnit/examples/triangle/bin/.gitignore new file mode 100644 index 0000000..72e8ffc --- /dev/null +++ b/lib/gamnit/examples/triangle/bin/.gitignore @@ -0,0 +1 @@ +* diff --git a/lib/gamnit/examples/triangle/package.ini b/lib/gamnit/examples/triangle/package.ini new file mode 100644 index 0000000..f673878 --- /dev/null +++ b/lib/gamnit/examples/triangle/package.ini @@ -0,0 +1,11 @@ +[package] +name=triangle +tags=example +maintainer=Alexis Laferrière +license=Apache-2.0 +[upstream] +browse=https://github.com/nitlang/nit/tree/master/lib/gamnit/examples/triangle/ +git=https://github.com/nitlang/nit.git +git.directory=lib/gamnit/examples/triangle/ +homepage=http://nitlanguage.org +issues=https://github.com/nitlang/nit/issues diff --git a/lib/gamnit/examples/triangle/res/.gitignore b/lib/gamnit/examples/triangle/res/.gitignore new file mode 100644 index 0000000..72e8ffc --- /dev/null +++ b/lib/gamnit/examples/triangle/res/.gitignore @@ -0,0 +1 @@ +* diff --git a/lib/gamnit/examples/triangle/src/portable_triangle.nit b/lib/gamnit/examples/triangle/src/portable_triangle.nit new file mode 100644 index 0000000..ac8e0e6 --- /dev/null +++ b/lib/gamnit/examples/triangle/src/portable_triangle.nit @@ -0,0 +1,138 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Portable example of using Gamnit with custom calls to OpenGL ES 2.0 +# +# References: +# * The book OpenGL ES 2.0 Programming Guide +# * https://code.google.com/p/opengles-book-samples/source/browse/trunk/LinuxX11/Chapter_2/Hello_Triangle/Hello_Triangle.c +module portable_triangle is + app_name "gamnit Triangle" + app_namespace "org.nitlanguage.triangle" + app_version(1, 0, git_revision) +end + +import gamnit + +redef class App + + # Our only program for the graphic card + var program: GLProgram is noautoinit + + # The only vertex sharder + var vertex_shader: GLVertexShader is noautoinit + + # The only fragment sharder + var fragment_shader: GLFragmentShader is noautoinit + + # Vertex data for the triangle + var vertex_array: VertexArray is noautoinit + + redef fun on_create + do + super + + var display = display + assert display != null + + print "Width: {display.width}" + print "Height: {display.height}" + + assert_no_gl_error + assert gl.shader_compiler else print "Cannot compile shaders" + + # GL program + program = new GLProgram + if not program.is_ok then + print "Program is not ok: {gl.error.to_s}\nLog:" + print program.info_log + abort + end + assert_no_gl_error + + # Vertex shader + vertex_shader = new GLVertexShader + assert vertex_shader.is_ok else print "Vertex shader is not ok: {gl.error}" + vertex_shader.source = """ + attribute vec4 vPosition; + void main() + { + gl_Position = vPosition; + } + """@glsl_vertex_shader.to_cstring + vertex_shader.compile + assert vertex_shader.is_compiled else print "Vertex shader compilation failed with: {vertex_shader.info_log} {program.info_log}" + assert_no_gl_error + + # Fragment shader + fragment_shader = new GLFragmentShader + assert fragment_shader.is_ok else print "Fragment shader is not ok: {gl.error}" + fragment_shader.source = """ + precision mediump float; + void main() + { + gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); + } + """@glsl_fragment_shader.to_cstring + fragment_shader.compile + assert fragment_shader.is_compiled else print "Fragment shader compilation failed with: {fragment_shader.info_log}" + assert_no_gl_error + + # Attach to program + program.attach_shader vertex_shader + program.attach_shader fragment_shader + program.bind_attrib_location(0, "vPosition") + program.link + assert program.is_linked else print "Linking failed: {program.info_log}" + assert_no_gl_error + + # Draw! + var vertices = [0.0, 0.5, 0.0, -0.5, -0.5, 0.0, 0.5, -0.5, 0.0] + vertex_array = new VertexArray(0, 3, vertices) + vertex_array.attrib_pointer + end + + redef fun frame_core + do + var display = display + if display != null then + gl.clear_color(0.5, 0.0, 0.5, 1.0) + + assert_no_gl_error + gl.viewport(0, 0, display.width, display.height) + gl.clear((new GLBuffer).color) + program.use + vertex_array.enable + + glDrawArrays(new GLDrawMode.triangles, 0, 3) + + display.flip + end + end + + redef fun on_stop + do + # Clean up + program.delete + vertex_shader.delete + fragment_shader.delete + + # Close gamnit + var display = display + if display != null then display.close + end +end + +if "NIT_TESTING".environ == "true" then exit(0) +super diff --git a/lib/gamnit/examples/triangle/src/standalone_triangle.nit b/lib/gamnit/examples/triangle/src/standalone_triangle.nit new file mode 100644 index 0000000..04e14db --- /dev/null +++ b/lib/gamnit/examples/triangle/src/standalone_triangle.nit @@ -0,0 +1,112 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Example of using `GamnitDisplay` to setup a screen for custom calls to OpenGL ES 2.0 +# +# This example does not support the lifecycle of mobile platforms, as such it only works on desktop computers. +# +# References: +# * The book OpenGL ES 2.0 Programming Guide +# * https://code.google.com/p/opengles-book-samples/source/browse/trunk/LinuxX11/Chapter_2/Hello_Triangle/Hello_Triangle.c +module standalone_triangle + +import app +import gamnit::display + +if "NIT_TESTING".environ == "true" then exit(0) + +# Setup gamnit +var display = new GamnitDisplay +display.setup + +var width = display.width +var height = display.height +print "Width: {width}" +print "Height: {height}" + +# Custom calls to OpenGL ES 2.0 +assert_no_gl_error +assert gl.shader_compiler else print "Cannot compile shaders" + +# GL program +print gl.error.to_s +var program = new GLProgram +if not program.is_ok then + print "Program is not ok: {gl.error.to_s}\nLog:" + print program.info_log + abort +end +assert_no_gl_error + +# Vertex shader +var vertex_shader = new GLVertexShader +assert vertex_shader.is_ok else print "Vertex shader is not ok: {gl.error}" +vertex_shader.source = """ +attribute vec4 vPosition; +void main() +{ + gl_Position = vPosition; +} +"""@glsl_vertex_shader.to_cstring +vertex_shader.compile +assert vertex_shader.is_compiled else print "Vertex shader compilation failed with: {vertex_shader.info_log} {program.info_log}" +assert_no_gl_error + +# Fragment shader +var fragment_shader = new GLFragmentShader +assert fragment_shader.is_ok else print "Fragment shader is not ok: {gl.error}" +fragment_shader.source = """ +precision mediump float; +void main() +{ + gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); +} +"""@glsl_fragment_shader.to_cstring +fragment_shader.compile +assert fragment_shader.is_compiled else print "Fragment shader compilation failed with: {fragment_shader.info_log}" +assert_no_gl_error + +# Attach to program +program.attach_shader vertex_shader +program.attach_shader fragment_shader +program.bind_attrib_location(0, "vPosition") +program.link +assert program.is_linked else print "Linking failed: {program.info_log}" +assert_no_gl_error + +# Draw! +var vertices = [0.0, 0.5, 0.0, -0.5, -0.5, 0.0, 0.5, -0.5, 0.0] +var vertex_array = new VertexArray(0, 3, vertices) +vertex_array.attrib_pointer +gl.clear_color(0.5, 0.0, 0.5, 1.0) +for i in [0..1000[ do + printn "." + assert_no_gl_error + gl.viewport(0, 0, width, height) + gl.clear((new GLBuffer).color) + program.use + vertex_array.enable + + glDrawArrays(new GLDrawMode.triangles, 0, 3) + + display.flip +end + +# Clean up +program.delete +vertex_shader.delete +fragment_shader.delete + +# Close gamnit +display.close diff --git a/lib/gamnit/gamnit.nit b/lib/gamnit/gamnit.nit index 2fa5b8e..43ec95c 100644 --- a/lib/gamnit/gamnit.nit +++ b/lib/gamnit/gamnit.nit @@ -14,3 +14,54 @@ # Game and multimedia framework for Nit module gamnit + +import app + +import display + +import gamnit_android is conditional(android) + +redef class App + + # Main `GamnitDisplay` initialized by `on_create` + var display: nullable GamnitDisplay = null + + redef fun on_create + do + super + + var display = new GamnitDisplay + display.setup + self.display = display + end + + # Core of the frame logic, executed only when the display is visible + # + # This method should be redefined by user modules to customize the behavior of the game. + protected fun frame_core do end + + # Full frame logic, executed even if the display is not visible + # + # This method wraps `frame_core` and other services to be executed in the main app loop. + # + # To customize the behavior on each turn, it is preferable to redefined `frame_core`. + # Still, `frame_full` can be redefined with care for more control. + protected fun frame_full + do + var display = display + if display != null then frame_core + + feed_events + end + + redef fun run + do + # TODO manage exit condition + loop frame_full + end + + # Loop on available events and feed them back to the app + # + # The implementation varies per platform. + private fun feed_events do end +end diff --git a/lib/gamnit/gamnit_android.nit b/lib/gamnit/gamnit_android.nit new file mode 100644 index 0000000..647c741 --- /dev/null +++ b/lib/gamnit/gamnit_android.nit @@ -0,0 +1,24 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Support services for Gamnit on Android +module gamnit_android + +import android + +intrude import gamnit + +redef class App + redef fun feed_events do app.poll_looper 0 +end diff --git a/lib/gamnit/project.ini b/lib/gamnit/package.ini similarity index 96% rename from lib/gamnit/project.ini rename to lib/gamnit/package.ini index 8a930eb..ad9c8cb 100644 --- a/lib/gamnit/project.ini +++ b/lib/gamnit/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=gamnit tags=game,lib maintainer=Alexis Laferrière diff --git a/lib/geometry/project.ini b/lib/geometry/package.ini similarity index 96% rename from lib/geometry/project.ini rename to lib/geometry/package.ini index 2340920..077c7b6 100644 --- a/lib/geometry/project.ini +++ b/lib/geometry/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=geometry tags=algo,lib maintainer=Romain Chanoir diff --git a/lib/gettext/project.ini b/lib/gettext/package.ini similarity index 96% rename from lib/gettext/project.ini rename to lib/gettext/package.ini index f16b6c4..d4f369e 100644 --- a/lib/gettext/project.ini +++ b/lib/gettext/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=gettext tags=i18n,lib maintainer=Lucas Bajolet diff --git a/lib/github/project.ini b/lib/github/package.ini similarity index 96% rename from lib/github/project.ini rename to lib/github/package.ini index 611019c..030bbd7 100644 --- a/lib/github/project.ini +++ b/lib/github/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=github tags=web,lib maintainer=Alexandre Terrasa diff --git a/lib/glesv2/examples/opengles2_hello_triangle.nit b/lib/glesv2/examples/opengles2_hello_triangle.nit index 48d49ab..3a1e1c5 100644 --- a/lib/glesv2/examples/opengles2_hello_triangle.nit +++ b/lib/glesv2/examples/opengles2_hello_triangle.nit @@ -168,7 +168,7 @@ for i in [0..10000[ do gl.clear((new GLBuffer).color) program.use vertex_array.enable - vertex_array.draw_arrays_triangles + glDrawArrays(new GLDrawMode.triangles, 0, 3) egl_display.swap_buffers(surface) end diff --git a/lib/glesv2/glesv2.nit b/lib/glesv2/glesv2.nit index 4e71e1f..9c3e1d7 100644 --- a/lib/glesv2/glesv2.nit +++ b/lib/glesv2/glesv2.nit @@ -37,6 +37,7 @@ module glesv2 is end import android::aware +intrude import c in "C Header" `{ #include @@ -296,38 +297,106 @@ class VertexArray # Number of data per vertex var count: Int - protected var glfloat_array: GLfloatArray + protected var glfloat_array: NativeGLfloatArray init(index, count: Int, array: Array[Float]) do self.index = index self.count = count - self.glfloat_array = new GLfloatArray(array) + self.glfloat_array = new NativeGLfloatArray(array.length) + for k in [0..array.length[ do + glfloat_array[k] = array[k] + end end fun attrib_pointer do attrib_pointer_intern(index, count, glfloat_array) - private fun attrib_pointer_intern(index, count: Int, array: GLfloatArray) `{ + private fun attrib_pointer_intern(index, count: Int, array: NativeGLfloatArray) `{ glVertexAttribPointer(index, count, GL_FLOAT, GL_FALSE, 0, array); `} - fun enable do enable_intern(index) - private fun enable_intern(index: Int) `{ glEnableVertexAttribArray(index); `} + # Enable this vertex attribute array + fun enable do glEnableVertexAttribArray(index) - fun draw_arrays_triangles do draw_arrays_triangles_intern(index, count) - private fun draw_arrays_triangles_intern(index, count: Int) `{ - glDrawArrays(GL_TRIANGLES, index, count); - `} + # Disable this vertex attribute array + fun disable do glDisableVertexAttribArray(index) end +# Enable the generic vertex attribute array at `index` +fun glEnableVertexAttribArray(index: Int) `{ glEnableVertexAttribArray(index); `} + +# Disable the generic vertex attribute array at `index` +fun glDisableVertexAttribArray(index: Int) `{ glDisableVertexAttribArray(index); `} + +# Render primitives from array data +fun glDrawArrays(mode: GLDrawMode, from, count: Int) `{ glDrawArrays(mode, from, count); `} + +# Define an array of generic vertex attribute data +fun glVertexAttribPointer(index, size: Int, typ: GLDataType, normalized: Bool, stride: Int, array: NativeGLfloatArray) `{ + glVertexAttribPointer(index, size, typ, normalized, stride, array); +`} + +# Specify the value of a generic vertex attribute +fun glVertexAttrib1f(index: Int, x: Float) `{ glVertexAttrib1f(index, x); `} + +# Specify the value of a generic vertex attribute +fun glVertexAttrib2f(index: Int, x, y: Float) `{ glVertexAttrib2f(index, x, y); `} + +# Specify the value of a generic vertex attribute +fun glVertexAttrib3f(index: Int, x, y, z: Float) `{ glVertexAttrib3f(index, x, y, z); `} + +# Specify the value of a generic vertex attribute +fun glVertexAttrib4f(index: Int, x, y, z, w: Float) `{ glVertexAttrib4f(index, x, y, z, w); `} + +# Specify the value of a uniform variable for the current program object +fun glUniform1i(index, x: Int) `{ glUniform1i(index, x); `} + +# Specify the value of a uniform variable for the current program object +fun glUniform2i(index, x, y: Int) `{ glUniform2i(index, x, y); `} + +# Specify the value of a uniform variable for the current program object +fun glUniform3i(index, x, y, z: Int) `{ glUniform3i(index, x, y, z); `} + +# Specify the value of a uniform variable for the current program object +fun glUniform4i(index, x, y, z, w: Int) `{ glUniform4i(index, x, y, z, w); `} + +# TODO glUniform*f + # Low level array of `Float` -extern class GLfloatArray `{GLfloat *`} - new (array: Array[Float]) import Array[Float].length, Array[Float].[] `{ - int i; - int len = Array_of_Float_length(array); - GLfloat *vertex_array = malloc(sizeof(GLfloat)*len); - for (i = 0; i < len; i ++) vertex_array[i] = Array_of_Float__index(array, i); - return vertex_array; - `} +class GLfloatArray + super CArray[Float] + redef type NATIVE: NativeGLfloatArray + + init do native_array = new NativeGLfloatArray(length) + + # Create with the content of `array` + new from(array: Array[Float]) + do + var arr = new GLfloatArray(array.length) + arr.fill_from array + return arr + end + + # Fill with the content of `array` + fun fill_from(array: Array[Float]) + do + assert length >= array.length + for k in [0..array.length[ do + self[k] = array[k] + end + end +end + +# An array of `GLfloat` in C (`GLfloat*`) +extern class NativeGLfloatArray `{ GLfloat* `} + super NativeCArray + redef type E: Float + + new(size: Int) `{ return calloc(size, sizeof(GLfloat)); `} + + redef fun [](index) `{ return self[index]; `} + redef fun []=(index, val) `{ self[index] = val; `} + + redef fun +(offset) `{ return self + offset; `} end # General type for OpenGL enumerations @@ -375,30 +444,47 @@ do end end -# Texture minifying function -# -# Used by: `GLES::tex_parameter_min_filter` -extern class GLTextureMinFilter - super GLEnum +# Does `name` corresponds to a texture? +fun glIsTexture(name: Int): Bool `{ return glIsTexture(name); `} - new nearest `{ return GL_NEAREST; `} - new linear `{ return GL_LINEAR; `} -end +# Bind the named `texture` to a `target` +fun glBindTexture(target: GLTextureTarget, texture: Int) `{ glBindTexture(target, texture); `} -# Texture magnification function -# -# Used by: `GLES::tex_parameter_mag_filter` -extern class GLTextureMagFilter +# Set pixel storage modes +fun glPixelStorei(parameter: GLPack, val: Int) `{ glPixelStorei(parameter, val); `} + +# Symbolic name of the parameter to be set with `glPixelStorei` +extern class GLPack super GLEnum +end + +# Parameter to specify the alignment requirements for the start of each pixel row in memory +fun gl_PACK_ALIGNEMENT: GLPack `{ return GL_PACK_ALIGNMENT; `} + +# Parameter to specify the alignment requirements for the start of each pixel row in memory +fun gl_UNPACK_ALIGNEMENT: GLPack `{ return GL_UNPACK_ALIGNMENT; `} + +# TODO GL_PACK_ROW_LENGTH, GL_PACK_IMAGE_HEIGHT, GL_PACK_SKIP_PIXELS, GL_PACK_SKIP_ROWS, GL_PACK_SKIP_IMAGES +# GL_UNPACK_ROW_LENGTH, GL_UNPACK_IMAGE_HEIGHT, GL_UNPACK_SKIP_PIXELS, GL_UNPACK_SKIP_ROWS, GL_UNPACK_SKIP_IMAGES - new nearest `{ return GL_NEAREST; `} - new linear `{ return GL_LINEAR; `} - new nearest_mipmap_nearest `{ return GL_NEAREST_MIPMAP_NEAREST; `} - new linear_mipmap_nearest `{ return GL_LINEAR_MIPMAP_NEAREST; `} - new nearest_mipmap_linear `{ return GL_NEAREST_MIPMAP_LINEAR; `} - new linear_mipmap_linear `{ return GL_LINEAR_MIPMAP_LINEAR; `} +# Specify a two-dimensional texture image +fun glTexImage2D(target: GLTextureTarget, level, internalformat, width, height, border: Int, + format: GLPixelFormat, typ: GLPixelType, data: NativeCByteArray) `{ + glTexImage2D(target, level, internalformat, width, height, border, format, typ, data); +`} + +# Texture minifying and magnifying function +extern class GLTextureFilter + super GLEnum end +fun gl_NEAREST: GLTextureFilter `{ return GL_NEAREST; `} +fun gl_LINEAR: GLTextureFilter `{ return GL_LINEAR; `} +fun gl_NEAREST_MIPMAP_NEAREST: GLTextureFilter `{ return GL_NEAREST_MIPMAP_NEAREST; `} +fun gl_LINEAR_MIPMAP_NEAREST: GLTextureFilter `{ return GL_LINEAR_MIPMAP_NEAREST; `} +fun gl_NEAREST_MIPMAP_NINEAR: GLTextureFilter `{ return GL_NEAREST_MIPMAP_LINEAR; `} +fun gl_LINEAR_MIPMAP_LINEAR: GLTextureFilter `{ return GL_LINEAR_MIPMAP_LINEAR; `} + # Wrap parameter of a texture # # Used by: `tex_parameter_wrap_*` @@ -411,15 +497,19 @@ extern class GLTextureWrap end # Target texture -# -# Used by: `tex_parameter_*` extern class GLTextureTarget super GLEnum - - new flat `{ return GL_TEXTURE_2D; `} - new cube_map `{ return GL_TEXTURE_CUBE_MAP; `} end +# Two-dimensional texture +fun gl_TEXTURE_2D: GLTextureTarget `{ return GL_TEXTURE_2D; `} + +# Cube map texture +fun gl_TEXTURE_CUBE_MAP: GLTextureTarget `{ return GL_TEXTURE_CUBE_MAP; `} + +# TODO GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, +# GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z + # A server-side capability class GLCap @@ -439,6 +529,52 @@ class GLCap redef fun hash do return val redef fun ==(o) do return o != null and is_same_type(o) and o.hash == self.hash end + +# Attach a renderbuffer object to a framebuffer object +fun glFramebufferRenderbuffer(target: GLFramebufferTarget, attachment: GLAttachment, + renderbuffertarget: GLRenderbufferTarget, renderbuffer: Int) `{ + glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer); +`} + +# Establish data storage, `format` and dimensions of the `target` renderbuffer object's image +fun glRenderbufferStorage(target: GLRenderbufferTarget, format: GLRenderbufferFormat, width, height: Int) `{ + glRenderbufferStorage(GL_RENDERBUFFER, format, width, height); +`} + +# Format for a renderbuffer +extern class GLRenderbufferFormat + super GLEnum +end + +# 4 red, 4 green, 4 blue, 4 alpha bits format +fun gl_RGBA4: GLRenderbufferFormat `{ return GL_RGBA4; `} + +# 5 red, 6 green, 5 blue bits format +fun gl_RGB565: GLRenderbufferFormat `{ return GL_RGB565; `} + +# 5 red, 5 green, 5 blue, 1 alpha bits format +fun gl_RGB_A1: GLRenderbufferFormat `{ return GL_RGB5_A1; `} + +# 16 depth bits format +fun gl_DEPTH_COMPNENT16: GLRenderbufferFormat `{ return GL_DEPTH_COMPONENT16; `} + +# 8 stencil bits format +fun gl_STENCIL_INDEX8: GLRenderbufferFormat `{ return GL_STENCIL_INDEX8; `} + +# Renderbuffer attachment point to a framebuffer +extern class GLAttachment + super GLEnum +end + +# First color attachment point +fun gl_COLOR_ATTACHMENT0: GLAttachment `{ return GL_COLOR_ATTACHMENT0; `} + +# Depth attachment point +fun gl_DEPTH_ATTACHMENT: GLAttachment `{ return GL_DEPTH_ATTACHMENT; `} + +# Stencil attachment +fun gl_STENCIL_ATTACHMENT: GLAttachment `{ return GL_STENCIL_ATTACHMENT; `} + redef class Sys private var gles = new GLES is lazy end @@ -544,20 +680,20 @@ class GLES # # Foreign: glReadPixel fun read_pixels(x, y, width, height: Int, format: GLPixelFormat, typ: GLPixelType, data: Pointer) `{ - glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data); + glReadPixels(x, y, width, height, format, typ, data); `} # Set the texture minifying function # # Foreign: glTexParameter with GL_TEXTURE_MIN_FILTER - fun tex_parameter_min_filter(target: GLTextureTarget, value: GLTextureMinFilter) `{ + fun tex_parameter_min_filter(target: GLTextureTarget, value: GLTextureFilter) `{ glTexParameteri(target, GL_TEXTURE_MIN_FILTER, value); `} # Set the texture magnification function # # Foreign: glTexParameter with GL_TEXTURE_MAG_FILTER - fun tex_parameter_mag_filter(target: GLTextureTarget, value: GLTextureMagFilter) `{ + fun tex_parameter_mag_filter(target: GLTextureTarget, value: GLTextureFilter) `{ glTexParameteri(target, GL_TEXTURE_MAG_FILTER, value); `} @@ -619,6 +755,23 @@ fun glHint(target: GLHintTarget, mode: GLHintMode) `{ glHint(target, mode); `} +# Generate and fill set of mipmaps for the texture object `target` +fun glGenerateMipmap(target: GLTextureTarget) `{ glGenerateMipmap(target); `} + +# Bind the named `buffer` object +fun glBindBuffer(target: GLArrayBuffer, buffer: Int) `{ glBindBuffer(target, buffer); `} + +# Target to which bind the buffer with `glBindBuffer` +extern class GLArrayBuffer + super GLEnum +end + +# Array buffer target +fun gl_ARRAY_BUFFER: GLArrayBuffer `{ return GL_ARRAY_BUFFER; `} + +# Element array buffer +fun gl_ELEMENT_ARRAY_BUFFER: GLArrayBuffer `{ return GL_ELEMENT_ARRAY_BUFFER; `} + # Completeness status of a framebuffer object fun glCheckFramebufferStatus(target: GLFramebufferTarget): GLFramebufferStatus `{ return glCheckFramebufferStatus(target); @@ -686,6 +839,12 @@ fun gl_NICEST: GLHintMode `{ return GL_NICEST; `} # No preference fun gl_DONT_CARE: GLHintMode `{ return GL_DONT_CARE; `} +# Attach a level of a texture object as a logical buffer to the currently bound framebuffer object +fun glFramebufferTexture2D(target: GLFramebufferTarget, attachment: GLAttachment, + texture_target: GLTextureTarget, texture, level: Int) `{ + glFramebufferTexture2D(target, attachment, texture_target, texture, level); +`} + # Entry point to OpenGL server-side capabilities class GLCapabilities diff --git a/lib/glesv2/project.ini b/lib/glesv2/package.ini similarity index 97% rename from lib/glesv2/project.ini rename to lib/glesv2/package.ini index 9dec9a4..5fcd07e 100644 --- a/lib/glesv2/project.ini +++ b/lib/glesv2/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=glesv2 tags=graphics,wrapper,lib maintainer=Alexis Laferrière diff --git a/lib/graphs/project.ini b/lib/graphs/package.ini similarity index 97% rename from lib/graphs/project.ini rename to lib/graphs/package.ini index a8c1513..41dde41 100644 --- a/lib/graphs/project.ini +++ b/lib/graphs/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=graphs tags=algo,lib maintainer=Alexandre Blondin Massé diff --git a/lib/gtk/project.ini b/lib/gtk/package.ini similarity index 96% rename from lib/gtk/project.ini rename to lib/gtk/package.ini index a31bf4d..1b7d4f4 100644 --- a/lib/gtk/project.ini +++ b/lib/gtk/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=gtk tags=ui,wrapper,lib maintainer=Alexis Laferrière diff --git a/lib/hash_debug.ini b/lib/hash_debug.ini index d1ca440..075ff53 100644 --- a/lib/hash_debug.ini +++ b/lib/hash_debug.ini @@ -1,4 +1,4 @@ -[project] +[package] name=hash_debug tags=debug,lib maintainer=Jean Privat diff --git a/lib/html/project.ini b/lib/html/package.ini similarity index 96% rename from lib/html/project.ini rename to lib/html/package.ini index 098a6b1..42df9f4 100644 --- a/lib/html/project.ini +++ b/lib/html/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=html tags=format,lib maintainer=Alexandre Terrasa diff --git a/lib/ini.ini b/lib/ini.ini index 205c91a..bc1adff 100644 --- a/lib/ini.ini +++ b/lib/ini.ini @@ -1,4 +1,4 @@ -[project] +[package] name=ini tags=format,lib maintainer=Alexandre Terrasa diff --git a/lib/ios/project.ini b/lib/ios/package.ini similarity index 96% rename from lib/ios/project.ini rename to lib/ios/package.ini index 9f72e4d..22034ae 100644 --- a/lib/ios/project.ini +++ b/lib/ios/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=ios tags=wrapper,lib maintainer=Alexis Laferrière diff --git a/lib/java/project.ini b/lib/java/package.ini similarity index 96% rename from lib/java/project.ini rename to lib/java/package.ini index 59aa607..41d7e23 100644 --- a/lib/java/project.ini +++ b/lib/java/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=java tags=java,wrapper,lib maintainer=Alexis Laferrière diff --git a/lib/json/project.ini b/lib/json/package.ini similarity index 96% rename from lib/json/project.ini rename to lib/json/package.ini index 0f67a08..41483ef 100644 --- a/lib/json/project.ini +++ b/lib/json/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=json tags=format,lib maintainer=Alexis Laferrière diff --git a/lib/jvm.ini b/lib/jvm.ini index 2db3b5c..c3a50c1 100644 --- a/lib/jvm.ini +++ b/lib/jvm.ini @@ -1,4 +1,4 @@ -[project] +[package] name=jvm tags=java,wrapper,lib maintainer=Alexis Laferrière diff --git a/lib/libevent.ini b/lib/libevent.ini index 28443b8..2c8ffea 100644 --- a/lib/libevent.ini +++ b/lib/libevent.ini @@ -1,4 +1,4 @@ -[project] +[package] name=libevent tags=wrapper,lib maintainer=Alexis Laferrière diff --git a/lib/linux/linux.nit b/lib/linux/linux.nit index 8b90102..04a0c5d 100644 --- a/lib/linux/linux.nit +++ b/lib/linux/linux.nit @@ -18,3 +18,25 @@ module linux import app + +redef class App + redef fun setup + do + super + + on_create + on_restore_state + on_start + on_resume + end + + redef fun run + do + super + + on_pause + on_save_state + on_stop + on_destroy + end +end diff --git a/lib/linux/project.ini b/lib/linux/package.ini similarity index 96% rename from lib/linux/project.ini rename to lib/linux/package.ini index 8a8f7e5..11f52d8 100644 --- a/lib/linux/project.ini +++ b/lib/linux/package.ini @@ -1,4 +1,4 @@ -[project] +[package] name=linux tags=lib maintainer=Alexis Laferrière diff --git a/lib/markdown/markdown.nit b/lib/markdown/markdown.nit index 1bb8815..b9e2f6a 100644 --- a/lib/markdown/markdown.nit +++ b/lib/markdown/markdown.nit @@ -758,8 +758,11 @@ class HTMLDecorator end redef fun add_code(v, block) do - if block isa BlockFence and block.meta != null then - v.add "
"
+		var meta = block.meta
+		if meta != null then
+			v.add "
"
 		else
 			v.add "
"
 		end
@@ -1173,6 +1176,26 @@ abstract class Block
 			block = block.next
 		end
 	end
+
+	# The raw content of the block as a multi-line string.
+	fun raw_content: String do
+		var infence = self isa BlockFence
+		var text = new FlatBuffer
+		var line = self.block.first_line
+		while line != null do
+			if not line.is_empty then
+				var str = line.value
+				if not infence and str.has_prefix("    ") then
+					text.append str.substring(4, str.length - line.trailing)
+				else
+					text.append str
+				end
+			end
+			text.append "\n"
+			line = line.next
+		end
+		return text.write_to_string
+	end
 end
 
 # A block without any markdown specificities.
@@ -1213,6 +1236,9 @@ end
 class BlockCode
 	super Block
 
+	# Any string found after fence token.
+	var meta: nullable Text
+
 	# Number of char to skip at the beginning of the line.
 	#
 	# Block code lines start at 4 spaces.
@@ -1239,9 +1265,6 @@ end
 class BlockFence
 	super BlockCode
 
-	# Any string found after fence token.
-	var meta: nullable Text
-
 	# Fence code lines start at 0 spaces.
 	redef var line_start = 0
 end
diff --git a/lib/markdown/project.ini b/lib/markdown/package.ini
similarity index 96%
rename from lib/markdown/project.ini
rename to lib/markdown/package.ini
index 89446e0..c66f5a6 100644
--- a/lib/markdown/project.ini
+++ b/lib/markdown/package.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=markdown
 tags=format,lib
 maintainer=Alexandre Terrasa 
diff --git a/lib/md5.ini b/lib/md5.ini
index 24082f0..c24d0d6 100644
--- a/lib/md5.ini
+++ b/lib/md5.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=md5
 tags=encoding,lib
 maintainer=Alexis Laferrière 
diff --git a/lib/meta.ini b/lib/meta.ini
index f2bee33..cc1da56 100644
--- a/lib/meta.ini
+++ b/lib/meta.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=meta
 tags=lib
 maintainer=Jean Privat 
diff --git a/lib/mnit/linux/linux_app.nit b/lib/mnit/linux/linux_app.nit
index 938bfd8..7bc03a0 100644
--- a/lib/mnit/linux/linux_app.nit
+++ b/lib/mnit/linux/linux_app.nit
@@ -35,21 +35,6 @@ redef class App
 		display = new Opengles1Display
 
 		super
-
-		on_create
-		on_restore_state
-		on_start
-		on_resume
-	end
-
-	redef fun run
-	do
-		super
-
-		on_pause
-		on_save_state
-		on_stop
-		on_destroy
 	end
 
 	redef fun generate_input
diff --git a/lib/mnit/project.ini b/lib/mnit/package.ini
similarity index 96%
rename from lib/mnit/project.ini
rename to lib/mnit/package.ini
index 8b19d29..2239f95 100644
--- a/lib/mnit/project.ini
+++ b/lib/mnit/package.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=mnit
 tags=lib
 maintainer=Alexis Laferrière 
diff --git a/lib/mongodb/project.ini b/lib/mongodb/package.ini
similarity index 96%
rename from lib/mongodb/project.ini
rename to lib/mongodb/package.ini
index 5c13675..f492aa4 100644
--- a/lib/mongodb/project.ini
+++ b/lib/mongodb/package.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=mongodb
 tags=database,lib
 maintainer=Alexandre Terrasa 
diff --git a/lib/more_collections.ini b/lib/more_collections.ini
index 0f4e4e3..44b4af9 100644
--- a/lib/more_collections.ini
+++ b/lib/more_collections.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=more_collections
 tags=algo,lib
 maintainer=Jean Privat 
diff --git a/lib/mpd.ini b/lib/mpd.ini
index c687789..730b993 100644
--- a/lib/mpd.ini
+++ b/lib/mpd.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=mpd
 tags=sound,lib
 maintainer=Alexis Laferrière 
diff --git a/lib/mpi/project.ini b/lib/mpi/package.ini
similarity index 96%
rename from lib/mpi/project.ini
rename to lib/mpi/package.ini
index 8a3f9cd..40a0e31 100644
--- a/lib/mpi/project.ini
+++ b/lib/mpi/package.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=mpi
 tags=parallelism,lib
 maintainer=Alexis Laferrière 
diff --git a/lib/neo4j/project.ini b/lib/neo4j/package.ini
similarity index 96%
rename from lib/neo4j/project.ini
rename to lib/neo4j/package.ini
index 981b3ec..9cab771 100644
--- a/lib/neo4j/project.ini
+++ b/lib/neo4j/package.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=neo4j
 tags=database,lib
 maintainer=Alexandre Terrasa 
diff --git a/lib/nitcc_runtime.ini b/lib/nitcc_runtime.ini
index ae672b3..e905712 100644
--- a/lib/nitcc_runtime.ini
+++ b/lib/nitcc_runtime.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=nitcc_runtime
 tags=lib
 maintainer=Jean Privat 
diff --git a/lib/nitcorn/project.ini b/lib/nitcorn/package.ini
similarity index 96%
rename from lib/nitcorn/project.ini
rename to lib/nitcorn/package.ini
index 4dd2c83..0ea320a 100644
--- a/lib/nitcorn/project.ini
+++ b/lib/nitcorn/package.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=nitcorn
 tags=network,lib
 maintainer=Alexis Laferrière 
diff --git a/lib/niti_runtime.ini b/lib/niti_runtime.ini
index 200dbd0..7103e49 100644
--- a/lib/niti_runtime.ini
+++ b/lib/niti_runtime.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=niti_runtime
 tags=lib
 maintainer=Jean Privat 
diff --git a/lib/noise.ini b/lib/noise.ini
index 2c1968d..3917ab3 100644
--- a/lib/noise.ini
+++ b/lib/noise.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=noise
 tags=algo,lib
 maintainer=Alexis Laferrière 
diff --git a/lib/opts.ini b/lib/opts.ini
index b7e8fc8..ed8a3ca 100644
--- a/lib/opts.ini
+++ b/lib/opts.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=opts
 tags=cli,lib
 maintainer=Jean Privat 
diff --git a/lib/ordered_tree.ini b/lib/ordered_tree.ini
index abb5df0..840bb11 100644
--- a/lib/ordered_tree.ini
+++ b/lib/ordered_tree.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=ordered_tree
 tags=algo,lib
 maintainer=Jean Privat 
diff --git a/tests/alt/projects.ini b/lib/packages.ini
similarity index 100%
rename from tests/alt/projects.ini
rename to lib/packages.ini
diff --git a/lib/parser_base.ini b/lib/parser_base.ini
index db32dbd..28d65d4 100644
--- a/lib/parser_base.ini
+++ b/lib/parser_base.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=parser_base
 tags=format,lib
 maintainer=Lucas Bajolet 
diff --git a/lib/perfect_hashing.ini b/lib/perfect_hashing.ini
index d309a96..f4ce782 100644
--- a/lib/perfect_hashing.ini
+++ b/lib/perfect_hashing.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=perfect_hashing
 tags=algo,lib
 maintainer=Julien Pagès 
diff --git a/lib/performance_analysis.ini b/lib/performance_analysis.ini
index a6977ec..bcd67ff 100644
--- a/lib/performance_analysis.ini
+++ b/lib/performance_analysis.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=performance_analysis
 tags=debug,lib
 maintainer=Alexis Laferrière 
diff --git a/lib/pipeline.ini b/lib/pipeline.ini
index 1a558a0..6d11449 100644
--- a/lib/pipeline.ini
+++ b/lib/pipeline.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=pipeline
 tags=algo,lib
 maintainer=Jean Privat 
diff --git a/lib/pnacl/project.ini b/lib/pnacl/package.ini
similarity index 96%
rename from lib/pnacl/project.ini
rename to lib/pnacl/package.ini
index dd0b3da..c3e650b 100644
--- a/lib/pnacl/project.ini
+++ b/lib/pnacl/package.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=pnacl
 tags=platform,lib
 maintainer=Johan Kayser 
diff --git a/lib/poset.ini b/lib/poset.ini
index e5b5d3f..df6546f 100644
--- a/lib/poset.ini
+++ b/lib/poset.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=poset
 tags=algo,lib
 maintainer=Jean Privat 
diff --git a/lib/posix_ext.ini b/lib/posix_ext.ini
index 16b1708..680e8ee 100644
--- a/lib/posix_ext.ini
+++ b/lib/posix_ext.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=posix_ext
 tags=wrapper,lib
 maintainer=Alexis Laferrière 
diff --git a/lib/privileges/project.ini b/lib/privileges/package.ini
similarity index 96%
rename from lib/privileges/project.ini
rename to lib/privileges/package.ini
index e92dfbc..7c09a7c 100644
--- a/lib/privileges/project.ini
+++ b/lib/privileges/package.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=privileges
 tags=lib
 maintainer=Alexis Laferrière 
diff --git a/lib/progression.ini b/lib/progression.ini
index 5297892..63800ab 100644
--- a/lib/progression.ini
+++ b/lib/progression.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=progression
 tags=lib
 maintainer=Jean-Christophe Beaupré 
diff --git a/lib/pthreads/project.ini b/lib/pthreads/package.ini
similarity index 97%
rename from lib/pthreads/project.ini
rename to lib/pthreads/package.ini
index 292b853..bb5bd5f 100644
--- a/lib/pthreads/project.ini
+++ b/lib/pthreads/package.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=pthreads
 tags=parallelism,wrapper,lib
 maintainer=Alexis Laferrière 
diff --git a/lib/realtime.ini b/lib/realtime.ini
index e80fb32..7ca1264 100644
--- a/lib/realtime.ini
+++ b/lib/realtime.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=realtime
 tags=lib
 maintainer=Alexis Laferrière 
diff --git a/lib/ropes_debug.ini b/lib/ropes_debug.ini
index 8fa6a63..e221815 100644
--- a/lib/ropes_debug.ini
+++ b/lib/ropes_debug.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=ropes_debug
 tags=debug,lib
 maintainer=Lucas Bajolet 
diff --git a/lib/sax/project.ini b/lib/sax/package.ini
similarity index 97%
rename from lib/sax/project.ini
rename to lib/sax/package.ini
index 71d9bc2..d2cd8b3 100644
--- a/lib/sax/project.ini
+++ b/lib/sax/package.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=sax
 tags=xml,format,lib
 maintainer=Jean-Christophe Beaupré 
diff --git a/lib/saxophonit/project.ini b/lib/saxophonit/package.ini
similarity index 97%
rename from lib/saxophonit/project.ini
rename to lib/saxophonit/package.ini
index 30e6534..47bbfd0 100644
--- a/lib/saxophonit/project.ini
+++ b/lib/saxophonit/package.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=saxophonit
 tags=xml,format,lib
 maintainer=Jean-Christophe Beaupré 
diff --git a/lib/scene2d.ini b/lib/scene2d.ini
index 8633dcd..c25d427 100644
--- a/lib/scene2d.ini
+++ b/lib/scene2d.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=scene2d
 tags=game,lib
 maintainer=Jean Privat 
diff --git a/lib/sdl.ini b/lib/sdl.ini
index 4020e46..a61fc18 100644
--- a/lib/sdl.ini
+++ b/lib/sdl.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=sdl
 tags=graphics,wrapper,lib
 maintainer=Alexis Laferrière 
diff --git a/lib/sdl2/project.ini b/lib/sdl2/package.ini
similarity index 96%
rename from lib/sdl2/project.ini
rename to lib/sdl2/package.ini
index 5a919d5..688490d 100644
--- a/lib/sdl2/project.ini
+++ b/lib/sdl2/package.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=sdl2
 tags=graphics,wrapper,lib
 maintainer=Alexis Laferrière 
diff --git a/lib/sendmail.ini b/lib/sendmail.ini
index 09e35a1..5b714a3 100644
--- a/lib/sendmail.ini
+++ b/lib/sendmail.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=sendmail
 tags=network,lib
 maintainer=Alexis Laferrière 
diff --git a/lib/serialization/project.ini b/lib/serialization/package.ini
similarity index 97%
rename from lib/serialization/project.ini
rename to lib/serialization/package.ini
index b124e84..7bcdcc1 100644
--- a/lib/serialization/project.ini
+++ b/lib/serialization/package.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=serialization
 tags=lib
 maintainer=Alexis Laferrière 
diff --git a/lib/sexp.ini b/lib/sexp.ini
index ff6a8e7..bb9de0d 100644
--- a/lib/sexp.ini
+++ b/lib/sexp.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=sexp
 tags=format,lib
 maintainer=Lucas Bajolet 
diff --git a/lib/sha1.ini b/lib/sha1.ini
index 3b0a2e2..5d1c7d5 100644
--- a/lib/sha1.ini
+++ b/lib/sha1.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=sha1
 tags=encoding,lib
 maintainer=Lucas Bajolet 
diff --git a/lib/signals.ini b/lib/signals.ini
index 8dc022a..24d8750 100644
--- a/lib/signals.ini
+++ b/lib/signals.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=signals
 tags=wrapper,lib
 maintainer=Alexis Laferrière 
diff --git a/lib/socket/project.ini b/lib/socket/package.ini
similarity index 96%
rename from lib/socket/project.ini
rename to lib/socket/package.ini
index 425c71e..746114b 100644
--- a/lib/socket/project.ini
+++ b/lib/socket/package.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=socket
 tags=network,lib
 maintainer=Alexis Laferrière 
diff --git a/lib/sqlite3/project.ini b/lib/sqlite3/package.ini
similarity index 96%
rename from lib/sqlite3/project.ini
rename to lib/sqlite3/package.ini
index f995fb3..969906b 100644
--- a/lib/sqlite3/project.ini
+++ b/lib/sqlite3/package.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=sqlite3
 tags=database,lib
 maintainer=Alexis Laferrière 
diff --git a/lib/standard.ini b/lib/standard.ini
index 4e237cc..f726f17 100644
--- a/lib/standard.ini
+++ b/lib/standard.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=standard
 tags=lib
 maintainer=Jean Privat 
diff --git a/lib/symbol.ini b/lib/symbol.ini
index e26d60d..671b668 100644
--- a/lib/symbol.ini
+++ b/lib/symbol.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=symbol
 tags=lib
 maintainer=Jean Privat 
diff --git a/lib/template/project.ini b/lib/template/package.ini
similarity index 96%
rename from lib/template/project.ini
rename to lib/template/package.ini
index 110f7d1..583add3 100644
--- a/lib/template/project.ini
+++ b/lib/template/package.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=template
 tags=lib
 maintainer=Jean Privat 
diff --git a/lib/test_suite.ini b/lib/test_suite.ini
index 2004d3c..a32a29c 100644
--- a/lib/test_suite.ini
+++ b/lib/test_suite.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=test_suite
 tags=devel,lib
 maintainer=Alexandre Terrasa 
diff --git a/lib/trees/project.ini b/lib/trees/package.ini
similarity index 96%
rename from lib/trees/project.ini
rename to lib/trees/package.ini
index 20467d4..5cd0e35 100644
--- a/lib/trees/project.ini
+++ b/lib/trees/package.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=trees
 tags=algo,lib
 maintainer=Alexandre Terrasa 
diff --git a/lib/websocket/project.ini b/lib/websocket/package.ini
similarity index 96%
rename from lib/websocket/project.ini
rename to lib/websocket/package.ini
index e6bd0fc..842ea3c 100644
--- a/lib/websocket/project.ini
+++ b/lib/websocket/package.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=websocket
 tags=network,lib
 maintainer=Lucas Bajolet 
diff --git a/lib/x11.ini b/lib/x11.ini
index 12fa59e..d103b5c 100644
--- a/lib/x11.ini
+++ b/lib/x11.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=x11
 tags=ui,lib
 maintainer=Alexis Laferrière 
diff --git a/lib/xdg_basedir/project.ini b/lib/xdg_basedir/package.ini
similarity index 97%
rename from lib/xdg_basedir/project.ini
rename to lib/xdg_basedir/package.ini
index cf51920..8d154ae 100644
--- a/lib/xdg_basedir/project.ini
+++ b/lib/xdg_basedir/package.ini
@@ -1,4 +1,4 @@
-[project]
+[package]
 name=xdg_basedir
 tags=wrapper,lib
 maintainer=Alexis Laferrière 
diff --git a/misc/vim/plugin/nit.vim b/misc/vim/plugin/nit.vim
index bb8dd13..363a8f9 100644
--- a/misc/vim/plugin/nit.vim
+++ b/misc/vim/plugin/nit.vim
@@ -53,7 +53,7 @@ function NitComplete()
 		let g:acp_behaviorKeywordIgnores = ['new', 'var', 'in', 'do', 'els', 'end', 'ret', 'for', 'fun']
 
 		" Use nitls to compute all interesting files from the current directory and the standard library
-		for file in split(system('nitls -M standard .', '\n'))
+		for file in split(system('nitls -M core .', '\n'))
 			silent let &complete = &complete . ',s' . file
 			silent set complete?
 		endfor
diff --git a/share/man/nitls.md b/share/man/nitls.md
index b7fffc9..5fa7f48 100644
--- a/share/man/nitls.md
+++ b/share/man/nitls.md
@@ -1,6 +1,6 @@
 # NAME
 
-nitls - lists the projects, groups and paths of Nit sources files.
+nitls - lists the packages, groups and paths of Nit sources files.
 
 # SYNOPSIS
 
@@ -8,7 +8,7 @@ nitls [*options*] [*FILE*]...
 
 # DESCRIPTION
 
-`nitls` is used to list Nit files in directories and extract the module-group-project relation.
+`nitls` is used to list Nit files in directories and extract the module-group-package relation.
 
 It is basically a `ls` or a simple `find` specialized on `.nit` source files.
 
@@ -31,7 +31,7 @@ Show the tree of modules from the current directory.
 
     $ nitls -t
 
-Show the list of projects imported by the modules of the current directory.
+Show the list of packages imported by the modules of the current directory.
 
     $ nitls -d -P *.nit
 
@@ -43,24 +43,24 @@ Each combination of option
 
 Three presentation modes are available.
 
-### `-P`, `--project`
-List projects in a flat list (default).
+### `-P`, `--package`
+List packages in a flat list (default).
 
-Only project are displayed (and not the individual files).
+Only package are displayed (and not the individual files).
 
 ### `-t`, `--tree`
-List source files in their groups and projects.
+List source files in their groups and packages.
 
-Each `.nit` file is presented in a tree of projects and groups.
+Each `.nit` file is presented in a tree of packages and groups.
 
 ### `-s`, `--source`
 List source files in a flat list.
 
-Each `.nit` file is presented indivitually.
+Each `.nit` file is presented individually.
 
 The three modes are exclusives.
 
-The default mode is `--project` unless one on the argument is a group, then it is `--group`.
+The default mode is `--package` unless one on the argument is a group, then it is `--group`.
 
 ## COLLECT
 
@@ -74,12 +74,12 @@ List dependencies of given modules
 
 All imported modules are also considered.
 
-In --tree and --source modes, the modules direclty imported are also displayed.
+In --tree and --source modes, the modules directly imported are also displayed.
 
 ### `-k`, `--keep`
 Ignore errors and files that are not a Nit source file.
 
-When a file that is not a valid Nit module is encoutered, it is ignored and the rest of the files are
+When a file that is not a valid Nit module is encountered, it is ignored and the rest of the files are
 processed.
 
 Without this option, an error message is displayed and nitls terminates on such a case.
diff --git a/src/compiler/compiler_ffi/compiler_ffi.nit b/src/compiler/compiler_ffi/compiler_ffi.nit
index edf0a16..79c2f14 100644
--- a/src/compiler/compiler_ffi/compiler_ffi.nit
+++ b/src/compiler/compiler_ffi/compiler_ffi.nit
@@ -280,7 +280,7 @@ redef class MExplicitCast
 
 			var from_var = nitni_visitor.var_from_c("from", from)
 			from_var = nitni_visitor.box_extern(from_var, from)
-			var recv_var = nitni_visitor.type_test(from_var, to, "FFI isa")
+			var recv_var = nitni_visitor.type_test(from_var, to, "isa")
 			nitni_visitor.add("return {recv_var};")
 
 			nitni_visitor.add("\}")
@@ -316,7 +316,7 @@ redef class MExplicitCast
 			from_var = nitni_visitor.box_extern(from_var, from)
 
 			## test type
-			var check = nitni_visitor.type_test(from_var, to, "FFI cast")
+			var check = nitni_visitor.type_test(from_var, to, "as")
 			nitni_visitor.add("if (!{check}) \{")
 			nitni_visitor.add_abort("FFI cast failed")
 			nitni_visitor.add("\}")
diff --git a/src/doc/console_templates/console_model.nit b/src/doc/console_templates/console_model.nit
index 5d693b1..96b1a40 100644
--- a/src/doc/console_templates/console_model.nit
+++ b/src/doc/console_templates/console_model.nit
@@ -39,7 +39,7 @@ redef class MEntity
 
 	# Returns the mentity name with short signature.
 	#
-	# * MProject: `foo`
+	# * MPackage: `foo`
 	# * MGroup: `foo`
 	# * MModule: `foo`
 	# * MClass: `Foo[E]`
@@ -53,7 +53,7 @@ redef class MEntity
 
 	# Returns the complete MEntity declaration (modifiers + name + signature).
 	#
-	# * MProject: `project foo`
+	# * MPackage: `package foo`
 	# * MGroup: `group foo`
 	# * MModule: `module foo`
 	# * MClass: `private abstract class Foo[E: Object]`
@@ -70,10 +70,10 @@ redef class MEntity
 
 	# Returns `self` namespace formatted for console.
 	#
-	# * MProject: `mproject`
-	# * MGroup: `mproject(::group)`
+	# * MPackage: `mpackage`
+	# * MGroup: `mpackage(::group)`
 	# * MModule: `mgroup::mmodule`
-	# * MClass: `mproject::mclass`
+	# * MClass: `mpackage::mclass`
 	# * MClassDef: `mmodule::mclassdef`
 	# * MProperty: `mclass::mprop`
 	# * MPropdef: `mclassdef:mpropdef`
@@ -158,8 +158,8 @@ redef class MEntity
 	end
 end
 
-redef class MProject
-	redef var cs_modifiers = ["project"]
+redef class MPackage
+	redef var cs_modifiers = ["package"]
 	redef fun cs_namespace do return cs_name
 	redef fun cs_icon do return "P"
 	redef fun cs_location do return root.mmodules.first.location.to_s
@@ -171,12 +171,12 @@ redef class MGroup
 
 	# Depends if `self` is root or not.
 	#
-	# * If root `mproject`.
-	# * Else `mproject::self`.
+	# * If root `mpackage`.
+	# * Else `mpackage::self`.
 	redef fun cs_namespace do
 		var tpl = new FlatBuffer
-		tpl.append mproject.cs_namespace
-		if mproject.root != self then
+		tpl.append mpackage.cs_namespace
+		if mpackage.root != self then
 			tpl.append "::"
 			tpl.append cs_name
 		end
@@ -230,10 +230,10 @@ redef class MClass
 	redef fun cs_modifiers do return intro.cs_modifiers
 	redef fun cs_declaration do return intro.cs_declaration
 
-	# Returns `mproject::self`.
+	# Returns `mpackage::self`.
 	redef fun cs_namespace do
 		var tpl = new FlatBuffer
-		tpl.append intro_mmodule.mgroup.mproject.cs_namespace
+		tpl.append intro_mmodule.mgroup.mpackage.cs_namespace
 		tpl.append "::"
 		tpl.append cs_name
 		return tpl.write_to_string
diff --git a/src/doc/console_templates/console_templates.nit b/src/doc/console_templates/console_templates.nit
index 6e8f03e..fbeea29 100644
--- a/src/doc/console_templates/console_templates.nit
+++ b/src/doc/console_templates/console_templates.nit
@@ -73,7 +73,7 @@ redef class ConcernSection
 
 	redef fun rendering do
 		var mentity = self.mentity
-		if mentity isa MGroup and mentity.mproject.root == mentity then
+		if mentity isa MGroup and mentity.mpackage.root == mentity then
 			render_body
 		else
 			super
diff --git a/src/doc/doc_down.nit b/src/doc/doc_down.nit
index 5284dc1..e04abb9 100644
--- a/src/doc/doc_down.nit
+++ b/src/doc/doc_down.nit
@@ -99,10 +99,8 @@ private class NitdocDecorator
 	var toolcontext = new ToolContext
 
 	redef fun add_code(v, block) do
-		var meta = "nit"
-		if block isa BlockFence and block.meta != null then
-			meta = block.meta.to_s
-		end
+		var meta = block.meta or else "nit"
+
 		# Do not try to highlight non-nit code.
 		if meta != "nit" and meta != "nitish" then
 			v.add "
"
@@ -111,7 +109,7 @@ private class NitdocDecorator
 			return
 		end
 		# Try to parse code
-		var code = code_from_block(block)
+		var code = block.raw_content
 		var ast = toolcontext.parse_something(code)
 		if ast isa AError then
 			v.add "
"
@@ -150,25 +148,6 @@ private class NitdocDecorator
 		for i in [from..to[ do out.add buffer[i]
 		return out.write_to_string
 	end
-
-	fun code_from_block(block: BlockCode): String do
-		var infence = block isa BlockFence
-		var text = new FlatBuffer
-		var line = block.block.first_line
-		while line != null do
-			if not line.is_empty then
-				var str = line.value
-				if not infence and str.has_prefix("    ") then
-					text.append str.substring(4, str.length - line.trailing)
-				else
-					text.append str
-				end
-			end
-			text.append "\n"
-			line = line.next
-		end
-		return text.write_to_string
-	end
 end
 
 # Decorator for span elements.
diff --git a/src/doc/doc_phases/doc_extract.nit b/src/doc/doc_phases/doc_extract.nit
index 456d545..d35abfa 100644
--- a/src/doc/doc_phases/doc_extract.nit
+++ b/src/doc/doc_phases/doc_extract.nit
@@ -55,7 +55,7 @@ class ExtractionPhase
 		doc.populate(self)
 	end
 
-	# Should we exclude this `mproject` from the documentation?
+	# Should we exclude this `mpackage` from the documentation?
 	fun ignore_mentity(mentity: MEntity): Bool do
 		if mentity isa MModule then
 			return mentity.is_fictive or mentity.is_test_suite
@@ -79,8 +79,8 @@ end
 # TODO Should I rebuild a new Model from filtered data?
 redef class DocModel
 
-	# MProjects that will be documented.
-	var mprojects = new HashSet[MProject]
+	# MPackages that will be documented.
+	var mpackages = new HashSet[MPackage]
 
 	# MGroups that will be documented.
 	var mgroups = new HashSet[MGroup]
@@ -102,17 +102,17 @@ redef class DocModel
 
 	# Populate `self` from internal `model`.
 	fun populate(v: ExtractionPhase) do
-		populate_mprojects(v)
+		populate_mpackages(v)
 		populate_mclasses(v)
 		populate_mproperties(v)
 	end
 
-	# Populates the `mprojects` set.
-	private fun populate_mprojects(v: ExtractionPhase) do
-		for mproject in model.mprojects do
-			if v.ignore_mentity(mproject) then continue
-			self.mprojects.add mproject
-			for mgroup in mproject.mgroups do
+	# Populates the `mpackages` set.
+	private fun populate_mpackages(v: ExtractionPhase) do
+		for mpackage in model.mpackages do
+			if v.ignore_mentity(mpackage) then continue
+			self.mpackages.add mpackage
+			for mgroup in mpackage.mgroups do
 				if v.ignore_mentity(mgroup) then continue
 				self.mgroups.add mgroup
 				for mmodule in mgroup.mmodules do
@@ -152,7 +152,7 @@ redef class DocModel
 	# FIXME invalidate cache if `self` is modified.
 	var mentities: Collection[MEntity] is lazy do
 		var res = new HashSet[MEntity]
-		res.add_all mprojects
+		res.add_all mpackages
 		res.add_all mgroups
 		res.add_all mmodules
 		res.add_all mclasses
@@ -178,7 +178,7 @@ redef class DocModel
 	#
 	# Path can be the shortest possible to disambiguise like `Class::property`.
 	# In case of larger conflicts, a more complex namespace can be given like
-	# `project::module::Class::prop`.
+	# `package::module::Class::prop`.
 	fun mentities_by_namespace(namespace: String): Array[MEntity] do
 		var res = new Array[MEntity]
 		for mentity in mentities do
@@ -206,7 +206,7 @@ redef class MEntity
 	end
 end
 
-redef class MProject
+redef class MPackage
 	redef fun mentities_by_namespace(namespace, res) do lookup_in(mgroups, namespace, res)
 end
 
diff --git a/src/doc/doc_phases/doc_html.nit b/src/doc/doc_phases/doc_html.nit
index 722724b..ebc1193 100644
--- a/src/doc/doc_phases/doc_html.nit
+++ b/src/doc/doc_phases/doc_html.nit
@@ -46,7 +46,7 @@ redef class ToolContext
 	# Display a custom brand or logo in the documentation top menu.
 	var opt_custom_brand = new OptionString("custom link to external site", "--custom-brand")
 
-	# Display a custom introduction text before the projects overview.
+	# Display a custom introduction text before the packages overview.
 	var opt_custom_intro = new OptionString("custom intro text for homepage", "--custom-overview-text")
 	# Display a custom footer on each documentation page.
 	#
@@ -68,7 +68,7 @@ redef class ToolContext
 	# FIXME redo the plugin
 	var opt_github_base_sha1 = new OptionString("Git sha1 of base commit used to create pull request", "--github-base-sha1")
 	# FIXME redo the plugin
-	var opt_github_gitdir = new OptionString("Git working directory used to resolve path name (ex: /home/me/myproject/)", "--github-gitdir")
+	var opt_github_gitdir = new OptionString("Git working directory used to resolve path name (ex: /home/me/mypackage/)", "--github-gitdir")
 
 	redef init do
 		super
@@ -257,11 +257,11 @@ redef class ReadmePage
 
 	redef fun init_topmenu(v, doc) do
 		super
-		var mproject = mentity.mproject
+		var mpackage = mentity.mpackage
 		if not mentity.is_root then
-			topmenu.add_li new ListItem(new Link(mproject.nitdoc_url, mproject.html_name))
+			topmenu.add_li new ListItem(new Link(mpackage.nitdoc_url, mpackage.html_name))
 		end
-		topmenu.add_li new ListItem(new Link(html_url, mproject.html_name))
+		topmenu.add_li new ListItem(new Link(html_url, mpackage.html_name))
 		topmenu.active_item = topmenu.items.last
 	end
 
@@ -275,11 +275,11 @@ end
 redef class MGroupPage
 	redef fun init_topmenu(v, doc) do
 		super
-		var mproject = mentity.mproject
+		var mpackage = mentity.mpackage
 		if not mentity.is_root then
-			topmenu.add_li new ListItem(new Link(mproject.nitdoc_url, mproject.html_name))
+			topmenu.add_li new ListItem(new Link(mpackage.nitdoc_url, mpackage.html_name))
 		end
-		topmenu.add_li new ListItem(new Link(html_url, mproject.html_name))
+		topmenu.add_li new ListItem(new Link(html_url, mpackage.html_name))
 		topmenu.active_item = topmenu.items.last
 	end
 
@@ -323,8 +323,8 @@ end
 redef class MModulePage
 	redef fun init_topmenu(v, doc) do
 		super
-		var mproject = mentity.mproject
-		topmenu.add_li new ListItem(new Link(mproject.nitdoc_url, mproject.html_name))
+		var mpackage = mentity.mpackage
+		topmenu.add_li new ListItem(new Link(mpackage.nitdoc_url, mpackage.html_name))
 		topmenu.add_li new ListItem(new Link(mentity.nitdoc_url, mentity.html_name))
 		topmenu.active_item = topmenu.items.last
 	end
@@ -367,8 +367,8 @@ redef class MClassPage
 
 	redef fun init_topmenu(v, doc) do
 		super
-		var mproject = mentity.intro_mmodule.mgroup.mproject
-		topmenu.add_li new ListItem(new Link(mproject.nitdoc_url, mproject.html_name))
+		var mpackage = mentity.intro_mmodule.mgroup.mpackage
+		topmenu.add_li new ListItem(new Link(mpackage.nitdoc_url, mpackage.html_name))
 		topmenu.add_li new ListItem(new Link(html_url, mentity.html_name))
 		topmenu.active_item = topmenu.items.last
 	end
@@ -471,9 +471,9 @@ redef class MPropertyPage
 	redef fun init_topmenu(v, doc) do
 		super
 		var mmodule = mentity.intro_mclassdef.mmodule
-		var mproject = mmodule.mgroup.mproject
+		var mpackage = mmodule.mgroup.mpackage
 		var mclass = mentity.intro_mclassdef.mclass
-		topmenu.add_li new ListItem(new Link(mproject.nitdoc_url, mproject.html_name))
+		topmenu.add_li new ListItem(new Link(mpackage.nitdoc_url, mpackage.html_name))
 		topmenu.add_li new ListItem(new Link(mclass.nitdoc_url, mclass.html_name))
 		topmenu.add_li new ListItem(new Link(html_url, mentity.html_name))
 		topmenu.active_item = topmenu.items.last
@@ -495,8 +495,8 @@ redef class MEntitySection
 		if not page isa MEntityPage then return
 		var mentity = self.mentity
 		if mentity isa MGroup and mentity.is_root then
-			html_title = mentity.mproject.html_name
-			html_subtitle = mentity.mproject.html_declaration
+			html_title = mentity.mpackage.html_name
+			html_subtitle = mentity.mpackage.html_declaration
 		else if mentity isa MProperty then
 			var title = new Template
 			title.add mentity.html_name
@@ -559,7 +559,7 @@ end
 redef class DefinitionArticle
 	redef fun init_html_render(v, doc, page) do
 		var mentity = self.mentity
-		if mentity isa MProject or mentity isa MModule then
+		if mentity isa MPackage or mentity isa MModule then
 			var title = new Template
 			title.add mentity.html_icon
 			title.add mentity.html_namespace
diff --git a/src/doc/doc_phases/doc_readme.nit b/src/doc/doc_phases/doc_readme.nit
index 4e5e2dc..605ddac 100644
--- a/src/doc/doc_phases/doc_readme.nit
+++ b/src/doc/doc_phases/doc_readme.nit
@@ -235,7 +235,7 @@ redef class ArticleCommand
 	private fun filter_results(res: Array[MEntity]): Array[MEntity] do
 		var out = new Array[MEntity]
 		for e in res do
-			if e isa MProject then continue
+			if e isa MPackage then continue
 			if e isa MGroup then continue
 			out.add e
 		end
diff --git a/src/doc/doc_phases/doc_structure.nit b/src/doc/doc_phases/doc_structure.nit
index aaf137f..f2686e6 100644
--- a/src/doc/doc_phases/doc_structure.nit
+++ b/src/doc/doc_phases/doc_structure.nit
@@ -49,13 +49,13 @@ redef class OverviewPage
 	redef fun apply_structure(v, doc) do
 		var article = new HomeArticle("home.article", "Home")
 		root.add_child article
-		# Projects list
-		var mprojects = doc.model.mprojects.to_a
+		# Packages list
+		var mpackages = doc.model.mpackages.to_a
 		var sorter = new MConcernRankSorter
-		sorter.sort mprojects
-		var section = new DocSection("projects.section", "Projects")
-		for mproject in mprojects do
-			section.add_child new DefinitionArticle("{mproject.nitdoc_id}.definition", null, mproject)
+		sorter.sort mpackages
+		var section = new DocSection("packages.section", "Packages")
+		for mpackage in mpackages do
+			section.add_child new DefinitionArticle("{mpackage.nitdoc_id}.definition", null, mpackage)
 		end
 		article.add_child section
 	end
@@ -78,17 +78,17 @@ redef class MGroupPage
 		var section = new MEntitySection("{mentity.nitdoc_name}.section", null, mentity)
 		root.add_child section
 		if mentity.is_root then
-			section.add_child new IntroArticle("{mentity.mproject.nitdoc_id}.intro", null, mentity.mproject)
+			section.add_child new IntroArticle("{mentity.mpackage.nitdoc_id}.intro", null, mentity.mpackage)
 		else
 			section.add_child new IntroArticle("{mentity.nitdoc_id}.intro", null, mentity)
 		end
 		var concerns = self.concerns
 		if concerns == null or concerns.is_empty then return
 		# FIXME avoid diff
-		mentity.mproject.booster_rank = -1000
+		mentity.mpackage.booster_rank = -1000
 		mentity.booster_rank = -1000
 		concerns.sort_with(v.concerns_sorter)
-		mentity.mproject.booster_rank = 0
+		mentity.mpackage.booster_rank = 0
 		mentity.booster_rank = 0
 		section.add_child new ConcernsArticle("{mentity.nitdoc_id}.concerns", null, mentity, concerns)
 		for mentity in concerns do
@@ -109,11 +109,11 @@ redef class MModulePage
 		var concerns = self.concerns
 		if concerns == null or concerns.is_empty then return
 		# FIXME avoid diff
-		mentity.mgroup.mproject.booster_rank = -1000
+		mentity.mgroup.mpackage.booster_rank = -1000
 		mentity.mgroup.booster_rank = -1000
 		mentity.booster_rank = -1000
 		concerns.sort_with(v.concerns_sorter)
-		mentity.mgroup.mproject.booster_rank = 0
+		mentity.mgroup.mpackage.booster_rank = 0
 		mentity.mgroup.booster_rank = 0
 		mentity.booster_rank = 0
 		section.add_child new ConcernsArticle("{mentity.nitdoc_id}.concerns", null, mentity, concerns)
@@ -174,11 +174,11 @@ redef class MClassPage
 		var concerns = self.concerns
 		if concerns == null or concerns.is_empty then return
 		# FIXME diff hack
-		mentity.intro_mmodule.mgroup.mproject.booster_rank = -1000
+		mentity.intro_mmodule.mgroup.mpackage.booster_rank = -1000
 		mentity.intro_mmodule.mgroup.booster_rank = -1000
 		mentity.intro_mmodule.booster_rank = -1000
 		concerns.sort_with(v.concerns_sorter)
-		mentity.intro_mmodule.mgroup.mproject.booster_rank = 0
+		mentity.intro_mmodule.mgroup.mpackage.booster_rank = 0
 		mentity.intro_mmodule.mgroup.booster_rank = 0
 		mentity.intro_mmodule.booster_rank = 0
 		var constructors = new DocSection("{mentity.nitdoc_id}.constructors", "Constructors")
@@ -249,11 +249,11 @@ redef class MPropertyPage
 		var concerns = self.concerns
 		if concerns == null or concerns.is_empty then return
 		# FIXME diff hack
-		mentity.intro.mclassdef.mmodule.mgroup.mproject.booster_rank = -1000
+		mentity.intro.mclassdef.mmodule.mgroup.mpackage.booster_rank = -1000
 		mentity.intro.mclassdef.mmodule.mgroup.booster_rank = -1000
 		mentity.intro.mclassdef.mmodule.booster_rank = -1000
 		concerns.sort_with(v.concerns_sorter)
-		mentity.intro.mclassdef.mmodule.mgroup.mproject.booster_rank = 0
+		mentity.intro.mclassdef.mmodule.mgroup.mpackage.booster_rank = 0
 		mentity.intro.mclassdef.mmodule.mgroup.booster_rank = 0
 		mentity.intro.mclassdef.mmodule.booster_rank = 0
 		section.add_child new ConcernsArticle("{mentity.nitdoc_id}.concerns", null, mentity, concerns)
@@ -377,7 +377,7 @@ class DefinitionArticle
 	redef var is_hidden = false
 end
 
-# The main project article.
+# The main package article.
 class HomeArticle
 	super DocArticle
 end
@@ -439,7 +439,7 @@ redef class MConcern
 	fun concern_rank: Int is abstract
 end
 
-redef class MProject
+redef class MPackage
 	redef var concern_rank is lazy do
 		var max = 0
 		for mgroup in mgroups do
diff --git a/src/doc/html_templates/html_model.nit b/src/doc/html_templates/html_model.nit
index ed895ee..b8727de 100644
--- a/src/doc/html_templates/html_model.nit
+++ b/src/doc/html_templates/html_model.nit
@@ -28,7 +28,7 @@ redef class MEntity
 
 	# Returns the mentity name without short signature.
 	#
-	# * MProject: `foo`
+	# * MPackage: `foo`
 	# * MGroup: `foo`
 	# * MModule: `foo`
 	# * MClass: `Foo[E]`
@@ -66,7 +66,7 @@ redef class MEntity
 
 	# Returns the complete MEntity declaration decorated with HTML.
 	#
-	# * MProject: `project foo`
+	# * MPackage: `package foo`
 	# * MGroup: `group foo`
 	# * MModule: `module foo`
 	# * MClass: `private abstract class Foo[E: Object]`
@@ -85,10 +85,10 @@ redef class MEntity
 
 	# Returns `self` namespace decorated with HTML links.
 	#
-	# * MProject: `mproject`
-	# * MGroup: `mproject(::group)`
+	# * MPackage: `mpackage`
+	# * MGroup: `mpackage(::group)`
 	# * MModule: `mgroup::mmodule`
-	# * MClass: `mproject::mclass`
+	# * MClass: `mpackage::mclass`
 	# * MClassDef: `mmodule::mclassdef`
 	# * MProperty: `mclass::mprop`
 	# * MPropdef: `mclassdef:mpropdef`
@@ -141,10 +141,10 @@ redef class MEntity
 	end
 end
 
-redef class MProject
+redef class MPackage
 	redef var nitdoc_id = name.to_cmangle is lazy
 	redef fun nitdoc_url do return root.nitdoc_url
-	redef var html_modifiers = ["project"]
+	redef var html_modifiers = ["package"]
 	redef fun html_namespace do return html_link
 	redef var css_classes = ["public"]
 end
@@ -162,12 +162,12 @@ redef class MGroup
 
 	# Depends if `self` is root or not.
 	#
-	# * If root `mproject`.
-	# * Else `mproject::self`.
+	# * If root `mpackage`.
+	# * Else `mpackage::self`.
 	redef fun html_namespace do
 		var tpl = new Template
-		tpl.add mproject.html_namespace
-		if mproject.root != self then
+		tpl.add mpackage.html_namespace
+		if mpackage.root != self then
 			tpl.add "::"
 			tpl.add html_link
 		end
@@ -233,10 +233,10 @@ redef class MClass
 	redef fun html_modifiers do return intro.html_modifiers
 	redef fun html_declaration do return intro.html_declaration
 
-	# Returns `mproject::self`.
+	# Returns `mpackage::self`.
 	redef fun html_namespace do
 		var tpl = new Template
-		tpl.add intro_mmodule.mgroup.mproject.html_namespace
+		tpl.add intro_mmodule.mgroup.mpackage.html_namespace
 		tpl.add "::"
 		tpl.add html_link
 		tpl.add ""
diff --git a/src/doc/html_templates/html_templates.nit b/src/doc/html_templates/html_templates.nit
index a497ad3..290f04b 100644
--- a/src/doc/html_templates/html_templates.nit
+++ b/src/doc/html_templates/html_templates.nit
@@ -449,7 +449,7 @@ redef class IntroArticle
 	redef fun render_body do
 		var tabs = new DocTabs("{html_id}.tabs", "")
 		var comment = mentity.html_documentation
-		if mentity isa MProject then
+		if mentity isa MPackage then
 			comment = mentity.html_synopsis
 		end
 		if comment != null then
@@ -506,7 +506,7 @@ redef class DefinitionArticle
 		var tabs = new DocTabs("{html_id}.tabs", "")
 		if not is_no_body then
 			var comment
-			if is_short_comment or mentity isa MProject then
+			if is_short_comment or mentity isa MPackage then
 				comment = mentity.html_synopsis
 			else
 				comment = mentity.html_documentation
diff --git a/src/ffi/extra_java_files.nit b/src/ffi/extra_java_files.nit
index 0e093a0..e6dfca2 100644
--- a/src/ffi/extra_java_files.nit
+++ b/src/ffi/extra_java_files.nit
@@ -28,7 +28,7 @@ redef class ToolContext
 end
 
 redef class MModule
-	# Extra Java files to compile with the project
+	# Extra Java files to compile with the module
 	private var extra_java_files: nullable Array[JavaFile] = null
 end
 
diff --git a/src/loader.nit b/src/loader.nit
index eb3d06d..a59ccf0 100644
--- a/src/loader.nit
+++ b/src/loader.nit
@@ -116,14 +116,14 @@ redef class ModelBuilder
 	#
 	# Each name can be:
 	#
-	# * a path to a module, a group or a directory of projects.
+	# * a path to a module, a group or a directory of packages.
 	# * a short name of a module or a group that are looked in the `paths` (-I)
 	#
 	# Then, for each entry, if it is:
 	#
 	# * a module, then is it parser and returned.
 	# * a group then recursively all its modules are parsed.
-	# * a directory of projects then all the modules of all projects are parsed.
+	# * a directory of packages then all the modules of all packages are parsed.
 	# * else an error is displayed.
 	#
 	# See `parse` for details.
@@ -205,7 +205,7 @@ redef class ModelBuilder
 		# First, look in groups
 		var c = mgroup
 		if c != null then
-			var r = c.mproject.root
+			var r = c.mpackage.root
 			assert r != null
 			scan_group(r)
 			var res = r.mmodule_paths_by_name(name)
@@ -215,10 +215,10 @@ redef class ModelBuilder
 		# Look at some known directories
 		var lookpaths = self.paths
 
-		# Look in the directory of the group project also (even if not explicitly in the path)
+		# Look in the directory of the group package also (even if not explicitly in the path)
 		if mgroup != null then
 			# path of the root group
-			var dirname = mgroup.mproject.root.filepath
+			var dirname = mgroup.mpackage.root.filepath
 			if dirname != null then
 				dirname = dirname.join_path("..").simplify_path
 				if not lookpaths.has(dirname) and dirname.file_exists then
@@ -308,7 +308,7 @@ redef class ModelBuilder
 	# See `identify_file`.
 	var identified_files = new Array[ModulePath]
 
-	# Identify a source file and load the associated project and groups if required.
+	# Identify a source file and load the associated package and groups if required.
 	#
 	# This method does what the user expects when giving an argument to a Nit tool.
 	#
@@ -317,7 +317,7 @@ redef class ModelBuilder
 	# * If `path` is a directory (with a `/`),
 	#   then the ModulePath of its default module is returned (if any)
 	# * If `path` is a simple identifier (eg. `digraph`),
-	#   then the main module of the project `digraph` is searched in `paths` and returned.
+	#   then the main module of the package `digraph` is searched in `paths` and returned.
 	#
 	# Silently return `null` if `path` does not exists or cannot be identified.
 	fun identify_file(path: String): nullable ModulePath
@@ -361,18 +361,18 @@ redef class ModelBuilder
 		var mgroup = get_mgroup(mgrouppath)
 
 		if mgroup == null then
-			# singleton project
-			var mproject = new MProject(pn, model)
-			mgroup = new MGroup(pn, mproject, null) # same name for the root group
+			# singleton package
+			var mpackage = new MPackage(pn, model)
+			mgroup = new MGroup(pn, mpackage, null) # same name for the root group
 			mgroup.filepath = path
-			mproject.root = mgroup
-			toolcontext.info("found singleton project `{pn}` at {path}", 2)
+			mpackage.root = mgroup
+			toolcontext.info("found singleton package `{pn}` at {path}", 2)
 
-			# Attach homonymous `ini` file to the project
+			# Attach homonymous `ini` file to the package
 			var inipath = path.dirname / "{pn}.ini"
 			if inipath.file_exists then
 				var ini = new ConfigTree(inipath)
-				mproject.ini = ini
+				mpackage.ini = ini
 			end
 		end
 
@@ -416,13 +416,13 @@ redef class ModelBuilder
 			return null
 		end
 
-		# By default, the name of the project or group is the base_name of the directory
+		# By default, the name of the package or group is the base_name of the directory
 		var pn = rdp.basename(".nit")
 
-		# Check `project.ini` that indicate a project
+		# Check `package.ini` that indicate a package
 		var ini = null
 		var parent = null
-		var inipath = dirpath / "project.ini"
+		var inipath = dirpath / "package.ini"
 		if inipath.file_exists then
 			ini = new ConfigTree(inipath)
 		end
@@ -436,16 +436,16 @@ redef class ModelBuilder
 				return null
 			end
 
-			# Special stopper `projects.ini`
-			if (dirpath/"projects.ini").file_exists then
-				# dirpath cannot be a project since it is a project directory
+			# Special stopper `packages.ini`
+			if (dirpath/"packages.ini").file_exists then
+				# dirpath cannot be a package since it is a package directory
 				mgroups[rdp] = null
 				return null
 			end
 
 			# check the parent directory (if it does not contain the stopper file)
 			var parentpath = dirpath.join_path("..").simplify_path
-			var stopper = parentpath / "projects.ini"
+			var stopper = parentpath / "packages.ini"
 			if not stopper.file_exists then
 				# Recursively get the parent group
 				parent = get_mgroup(parentpath)
@@ -459,20 +459,20 @@ redef class ModelBuilder
 
 		var mgroup
 		if parent == null then
-			# no parent, thus new project
-			if ini != null then pn = ini["project.name"] or else pn
-			var mproject = new MProject(pn, model)
-			mgroup = new MGroup(pn, mproject, null) # same name for the root group
-			mproject.root = mgroup
-			toolcontext.info("found project `{mproject}` at {dirpath}", 2)
-			mproject.ini = ini
+			# no parent, thus new package
+			if ini != null then pn = ini["package.name"] or else pn
+			var mpackage = new MPackage(pn, model)
+			mgroup = new MGroup(pn, mpackage, null) # same name for the root group
+			mpackage.root = mgroup
+			toolcontext.info("found package `{mpackage}` at {dirpath}", 2)
+			mpackage.ini = ini
 		else
-			mgroup = new MGroup(pn, parent.mproject, parent)
+			mgroup = new MGroup(pn, parent.mpackage, parent)
 			toolcontext.info("found sub group `{mgroup.full_name}` at {dirpath}", 2)
 		end
 
 		# search documentation
-		# in src first so the documentation of the project code can be distinct for the documentation of the project usage
+		# in src first so the documentation of the package code can be distinct for the documentation of the package usage
 		var readme = dirpath.join_path("README.md")
 		if not readme.file_exists then readme = dirpath.join_path("README")
 		if readme.file_exists then
@@ -524,8 +524,8 @@ redef class ModelBuilder
 		for f in p.files do
 			var fp = p/f
 			var g = get_mgroup(fp)
-			# Recursively scan for groups of the same project
-			if g != null and g.mproject == mgroup.mproject then
+			# Recursively scan for groups of the same package
+			if g != null and g.mpackage == mgroup.mpackage then
 				scan_group(g)
 			end
 			identify_file(fp)
@@ -668,11 +668,11 @@ redef class ModelBuilder
 			end
 		end
 
-		# Check for conflicting module names in the project
+		# Check for conflicting module names in the package
 		if mgroup != null then
 			var others = model.get_mmodules_by_name(mod_name)
 			if others != null then for other in others do
-				if other.mgroup!= null and other.mgroup.mproject == mgroup.mproject then
+				if other.mgroup!= null and other.mgroup.mpackage == mgroup.mpackage then
 					var node: ANode
 					if decl == null then node = nmodule else node = decl.n_name
 					error(node, "Error: a module named `{other.full_name}` already exists at {other.location}.")
@@ -728,8 +728,8 @@ redef class ModelBuilder
 
 		# If qualified and in a group
 		if mgroup != null then
-			# First search in the project
-			var r = mgroup.mproject.root
+			# First search in the package
+			var r = mgroup.mpackage.root
 			assert r != null
 			scan_group(r)
 			# Get all modules with the final name
@@ -1012,7 +1012,7 @@ class ModulePath
 	# The human path of the module
 	var filepath: String
 
-	# The group (and the project) of the possible module
+	# The group (and the package) of the possible module
 	var mgroup: MGroup
 
 	# The loaded module (if any)
@@ -1021,12 +1021,12 @@ class ModulePath
 	redef fun to_s do return filepath
 end
 
-redef class MProject
+redef class MPackage
 	# The associated `.ini` file, if any
 	#
 	# The `ini` file is given as is and might contain invalid or missing information.
 	#
-	# Some projects, like stand-alone projects or virtual projects have no `ini` file associated.
+	# Some packages, like stand-alone packages or virtual packages have no `ini` file associated.
 	var ini: nullable ConfigTree = null
 end
 
@@ -1036,7 +1036,7 @@ redef class MGroup
 
 	# Is the group interesting for a final user?
 	#
-	# Groups are mandatory in the model but for simple projects they are not
+	# Groups are mandatory in the model but for simple packages they are not
 	# always interesting.
 	#
 	# A interesting group has, at least, one of the following true:
diff --git a/src/metrics/detect_covariance.nit b/src/metrics/detect_covariance.nit
index 746ad9e..25463ad 100644
--- a/src/metrics/detect_covariance.nit
+++ b/src/metrics/detect_covariance.nit
@@ -204,7 +204,7 @@ private class DetectCovariancePhase
 
 		## ONLY covariance remains here
 
-		cpt_modules.inc(mmodule.mgroup.mproject.name)
+		cpt_modules.inc(mmodule.mgroup.mpackage.name)
 		cpt_classes.inc(sub.mclass)
 
 		# Track if `cpt_explanations` is already decided (used to fallback on unknown)
diff --git a/src/metrics/generate_hierarchies.nit b/src/metrics/generate_hierarchies.nit
index 6193b9c..ecbba30 100644
--- a/src/metrics/generate_hierarchies.nit
+++ b/src/metrics/generate_hierarchies.nit
@@ -44,20 +44,20 @@ end
 fun generate_module_hierarchy(toolcontext: ToolContext, given_mmodules: Collection[MModule])
 do
 	var model = given_mmodules.first.model
-	var dot = new MProjectDot(model)
+	var dot = new MPackageDot(model)
 
-	# Collect requested projects
+	# Collect requested packages
 	for m in given_mmodules do
 		var g = m.mgroup
 		if g == null then continue
-		dot.mprojects.add(g.mproject)
+		dot.mpackages.add(g.mpackage)
 	end
-	var projectpath = toolcontext.output_dir.join_path("project_hierarchy.dot")
-	print "generating project_hierarchy.dot"
-	dot.write_to_file(projectpath)
+	var packagepath = toolcontext.output_dir.join_path("package_hierarchy.dot")
+	print "generating package_hierarchy.dot"
+	dot.write_to_file(packagepath)
 
 	var modulepath = toolcontext.output_dir.join_path("module_hierarchy.dot")
-	dot.mprojects.add_all(model.mprojects)
+	dot.mpackages.add_all(model.mpackages)
 	print "generating module_hierarchy.dot"
 	dot.write_to_file(modulepath)
 end
diff --git a/src/metrics/inheritance_metrics.nit b/src/metrics/inheritance_metrics.nit
index d475562..1287c0f 100644
--- a/src/metrics/inheritance_metrics.nit
+++ b/src/metrics/inheritance_metrics.nit
@@ -59,11 +59,11 @@ private class InheritanceMetricsPhase
 		var model = toolcontext.modelbuilder.model
 		var mmodules = new HashSet[MModule]
 		var mclasses = new HashSet[MClass]
-		for mproject in model.mprojects do
+		for mpackage in model.mpackages do
 
-			print toolcontext.format_h2("\n ## project {mproject}")
+			print toolcontext.format_h2("\n ## package {mpackage}")
 
-			for mgroup in mproject.mgroups do
+			for mgroup in mpackage.mgroups do
 				if mgroup.mmodules.is_empty then continue
 
 				# Scalar metrics
diff --git a/src/metrics/mclasses_metrics.nit b/src/metrics/mclasses_metrics.nit
index ed41a9f..69b5b40 100644
--- a/src/metrics/mclasses_metrics.nit
+++ b/src/metrics/mclasses_metrics.nit
@@ -55,11 +55,11 @@ private class MClassesMetricsPhase
 
 		var model = toolcontext.modelbuilder.model
 		var mclasses = new HashSet[MClass]
-		for mproject in model.mprojects do
+		for mpackage in model.mpackages do
 
-			print toolcontext.format_h2("\n ## project {mproject}")
+			print toolcontext.format_h2("\n ## package {mpackage}")
 
-			for mgroup in mproject.mgroups do
+			for mgroup in mpackage.mgroups do
 				if mgroup.mmodules.is_empty then continue
 				metrics.clear
 
diff --git a/src/metrics/mmodules_metrics.nit b/src/metrics/mmodules_metrics.nit
index a7ac696..335831c 100644
--- a/src/metrics/mmodules_metrics.nit
+++ b/src/metrics/mmodules_metrics.nit
@@ -41,10 +41,10 @@ private class MModulesMetricsPhase
 
 		var model = toolcontext.modelbuilder.model
 		var mmodules = new HashSet[MModule]
-		for mproject in model.mprojects do
+		for mpackage in model.mpackages do
 
-			print  toolcontext.format_h2("\n ## project {mproject}")
-			for mgroup in mproject.mgroups do
+			print  toolcontext.format_h2("\n ## package {mpackage}")
+			for mgroup in mpackage.mgroups do
 				if mgroup.mmodules.is_empty then continue
 
 				# Scalar metrics
diff --git a/src/metrics/model_hyperdoc.nit b/src/metrics/model_hyperdoc.nit
index 9e66e73..ed91198 100644
--- a/src/metrics/model_hyperdoc.nit
+++ b/src/metrics/model_hyperdoc.nit
@@ -40,24 +40,24 @@ do
 	buf.append("\n\n")
 	buf.append("

Model

\n") - buf.append("

Projects

\n") - for mproject in model.mprojects do - buf.append("

Project {mproject}

\n") + buf.append("

Packages

\n") + for mpackage in model.mpackages do + buf.append("

Package {mpackage}

\n") buf.append("
\n") buf.append("
groups
\n") - for x in mproject.mgroups do + for x in mpackage.mgroups do buf.append("
{linkto(x)}
\n") end buf.append("
\n") end buf.append("

Groups

\n") - for mproject in model.mprojects do - for mgroup in mproject.mgroups do + for mpackage in model.mpackages do + for mgroup in mpackage.mgroups do buf.append("

Group {mgroup}

\n") buf.append("
\n") - buf.append("
project
\n") - buf.append("
{linkto(mproject)}
\n") + buf.append("
package
\n") + buf.append("
{linkto(mpackage)}
\n") buf.append("
filepath
\n") buf.append("
{mgroup.filepath.to_s}
\n") var p = mgroup.parent @@ -193,8 +193,8 @@ end private fun linkto(o: Object): String do - if o isa MProject then - return "{o}" + if o isa MPackage then + return "{o}" else if o isa MGroup then return "{o}" else if o isa MModule then diff --git a/src/metrics/nullables_metrics.nit b/src/metrics/nullables_metrics.nit index 62c8f71..6e9d7ff 100644 --- a/src/metrics/nullables_metrics.nit +++ b/src/metrics/nullables_metrics.nit @@ -44,11 +44,11 @@ private class NullablesMetricsPhase var model = toolcontext.modelbuilder.model var mclasses = new HashSet[MClass] - for mproject in model.mprojects do + for mpackage in model.mpackages do - print toolcontext.format_h2("\n ## project {mproject}") + print toolcontext.format_h2("\n ## package {mpackage}") - for mgroup in mproject.mgroups do + for mgroup in mpackage.mgroups do if mgroup.mmodules.is_empty then continue metrics.clear diff --git a/src/model/mdoc.nit b/src/model/mdoc.nit index 4e8c565..2035b06 100644 --- a/src/model/mdoc.nit +++ b/src/model/mdoc.nit @@ -39,7 +39,7 @@ redef class MEntity # The documentation associated to the entity or their main nested entity. # - # MProject fall-back to their root MGroup + # MPackage fall-back to their root MGroup # MGroup fall-back to their default_mmodule # Other entities do not fall-back # diff --git a/src/model/mmodule.nit b/src/model/mmodule.nit index 659660b..7e2e9b3 100644 --- a/src/model/mmodule.nit +++ b/src/model/mmodule.nit @@ -18,7 +18,7 @@ module mmodule import location -import mproject +import mpackage private import more_collections # The container class of a Nit object-oriented model. @@ -73,15 +73,15 @@ class MModule # The model considered redef var model: Model - # The group of module in the project if any + # The group of module in the package if any var mgroup: nullable MGroup - # The project of the module if any - # Safe alias for `mgroup.mproject` - fun mproject: nullable MProject + # The package of the module if any + # Safe alias for `mgroup.mpackage` + fun mpackage: nullable MPackage do var g = mgroup - if g == null then return null else return g.mproject + if g == null then return null else return g.mpackage end # The short name of the module @@ -98,24 +98,24 @@ class MModule # The canonical name of the module. # - # It is usually the `name` prefixed by the project's name. - # Example: `"project::name"` + # It is usually the `name` prefixed by the package's name. + # Example: `"package::name"` # - # If both names are the same (of if the module is project-less), then + # If both names are the same (of if the module is package-less), then # the short-name is used alone. redef var full_name is lazy do var mgroup = self.mgroup - if mgroup == null or mgroup.mproject.name == self.name then + if mgroup == null or mgroup.mpackage.name == self.name then return self.name else - return "{mgroup.mproject.name}::{self.name}" + return "{mgroup.mpackage.name}::{self.name}" end end # The namespace used for entities according to their visibility `v`. # - # Public entities use only the project as a namespace. - # Private entities use the `full_name` (i.e. "project::module") + # Public entities use only the package as a namespace. + # Private entities use the `full_name` (i.e. "package::module") # # This method is used by entities to implement their `full_name`. fun namespace_for(v: MVisibility): String do @@ -124,7 +124,7 @@ class MModule if mgroup == null then return full_name else - return mgroup.mproject.full_name + return mgroup.mpackage.full_name end end @@ -133,8 +133,8 @@ class MModule redef var c_name: String is lazy do var g = mgroup var res - if g != null and g.mproject.name != name then - res = g.mproject.name.to_cmangle + "__" + name.to_cmangle + if g != null and g.mpackage.name != name then + res = g.mpackage.name.to_cmangle + "__" + name.to_cmangle else res = name.to_cmangle end @@ -151,7 +151,7 @@ class MModule if mgroup == null then return c_name else - return mgroup.mproject.c_name + return mgroup.mpackage.c_name end end diff --git a/src/model/model.nit b/src/model/model.nit index e0c3280..8d6bf7a 100644 --- a/src/model/model.nit +++ b/src/model/model.nit @@ -614,7 +614,7 @@ class MClassDef # public gives 'p#A' # private gives 'p::m#A' return "{mmodule.namespace_for(mclass.visibility)}#{mclass.name}" - else if mclass.intro_mmodule.mproject != mmodule.mproject then + else if mclass.intro_mmodule.mpackage != mmodule.mpackage then # public gives 'q::n#p::A' # private gives 'q::n#p::m::A' return "{mmodule.full_name}#{mclass.full_name}" @@ -630,7 +630,7 @@ class MClassDef redef var c_name is lazy do if is_intro then return "{mmodule.c_namespace_for(mclass.visibility)}___{mclass.c_name}" - else if mclass.intro_mmodule.mproject == mmodule.mproject and mclass.visibility > private_visibility then + else if mclass.intro_mmodule.mpackage == mmodule.mpackage and mclass.visibility > private_visibility then return "{mmodule.c_name}___{mclass.name.to_cmangle}" else return "{mmodule.c_name}___{mclass.c_name}" @@ -1932,7 +1932,7 @@ abstract class MProperty # The canonical name of the property. # # It is the short-`name` prefixed by the short-name of the class and the full-name of the module. - # Example: "my_project::my_module::MyClass::my_method" + # Example: "my_package::my_module::MyClass::my_method" redef var full_name is lazy do return "{intro_mclassdef.mmodule.namespace_for(visibility)}::{intro_mclassdef.mclass.name}::{name}" end @@ -2250,14 +2250,14 @@ abstract class MPropDef res.append name else # Just try to simplify each part - if mclassdef.mmodule.mproject != mproperty.intro_mclassdef.mmodule.mproject then + if mclassdef.mmodule.mpackage != mproperty.intro_mclassdef.mmodule.mpackage then # precise "p::m" only if "p" != "r" res.append mproperty.intro_mclassdef.mmodule.full_name res.append "::" else if mproperty.visibility <= private_visibility then - # Same project ("p"=="q"), but private visibility, + # Same package ("p"=="q"), but private visibility, # does the module part ("::m") need to be displayed - if mclassdef.mmodule.namespace_for(mclassdef.mclass.visibility) != mproperty.intro_mclassdef.mmodule.mproject then + if mclassdef.mmodule.namespace_for(mclassdef.mclass.visibility) != mproperty.intro_mclassdef.mmodule.mpackage then res.append "::" res.append mproperty.intro_mclassdef.mmodule.name res.append "::" diff --git a/src/model/model_viz.nit b/src/model/model_viz.nit index 305cd23..66ab460 100644 --- a/src/model/model_viz.nit +++ b/src/model/model_viz.nit @@ -18,9 +18,9 @@ module model_viz import model import ordered_tree -# A simple specialisation of OrderedTree to display projects, groups and modules +# A simple specialisation of OrderedTree to display packages, groups and modules # FIXME do not use Object, but a better common interface of MModule and MGroup -class MProjectTree +class MPackageTree super OrderedTree[Object] # The model where to look for information @@ -28,7 +28,7 @@ class MProjectTree redef fun display(a) do if a isa MGroup then - if a.parent == null then return "{a.mproject.name} ({a.filepath.to_s})" + if a.parent == null then return "{a.mpackage.name} ({a.filepath.to_s})" return a.name + " (group)" else if a isa MModule then return a.name @@ -115,11 +115,11 @@ private class LinexComparator end redef class Model - # Generate a MProjectTree based on the projects, groups and modules known in the model - fun to_mproject_tree: MProjectTree + # Generate a MPackageTree based on the packages, groups and modules known in the model + fun to_mpackage_tree: MPackageTree do - var res = new MProjectTree(self) - for p in mprojects do + var res = new MPackageTree(self) + for p in mpackages do for g in p.mgroups do res.add(g.parent, g) for m in g.mmodules do @@ -131,19 +131,19 @@ redef class Model end end -# Generate graphiz files based on projects, groups and modules +# Generate graphiz files based on packages, groups and modules # # Interesting elements must be selected. See `mmodules`, `` -# Display configuration can be set. See `cluster_group`, `project_group` -class MProjectDot +# Display configuration can be set. See `cluster_group`, `package_group` +class MPackageDot super Writable # The model where to look for information var model: Model - # Set of projects to expand fully (ie all groups and modules are displayed) - # Initially empty, projects can be added - var mprojects = new HashSet[MProject] + # Set of packages to expand fully (ie all groups and modules are displayed) + # Initially empty, packages can be added + var mpackages = new HashSet[MPackage] # Set of modules to display # Initially empty, modules can be added @@ -157,17 +157,17 @@ class MProjectDot # Should groups be shown as clusters? var cluster_group = true is writable - # Should projects be shown as clusters? - var project_group = true is writable + # Should packages be shown as clusters? + var package_group = true is writable # Recursively generate node and clusters for a mgroup private fun dot_cluster(o: Writer, mgroup: MGroup) do # Open the cluster, if required if mgroup.parent == null then - # is is a root group, so display the project - if project_group then - o.write("subgraph cluster_{mgroup.object_id} \{\nlabel=\"{mgroup.mproject.name}\\n({mgroup.filepath.to_s})\"\ncolor=black\nstyle=dotted\n") + # is is a root group, so display the package + if package_group then + o.write("subgraph cluster_{mgroup.object_id} \{\nlabel=\"{mgroup.mpackage.name}\\n({mgroup.filepath.to_s})\"\ncolor=black\nstyle=dotted\n") end else if cluster_group then @@ -188,13 +188,13 @@ class MProjectDot # close the cluster if required if mgroup.parent == null then - if project_group then o.write("\}\n") + if package_group then o.write("\}\n") else if cluster_group then o.write("\}\n") end end - # Extends the set of `mmodules` by recursively adding the most specific imported modules of foreign projects + # Extends the set of `mmodules` by recursively adding the most specific imported modules of foreign packages fun collect_important_importation do var todo = new List[MModule] @@ -203,9 +203,9 @@ class MProjectDot var m = todo.pop for psm in m.in_importation.greaters do - if m.mgroup.mproject != psm.mgroup.mproject then continue + if m.mgroup.mpackage != psm.mgroup.mpackage then continue for ssm in psm.in_importation.direct_greaters do - if psm.mgroup.mproject == ssm.mgroup.mproject then continue + if psm.mgroup.mpackage == ssm.mgroup.mpackage then continue mmodules.add(ssm) todo.add(ssm) end @@ -218,9 +218,9 @@ class MProjectDot do # Collect interesting nodes for m in model.mmodules do - # filter out modules outside wanted projects + # filter out modules outside wanted packages if m.mgroup == null then continue - if not mprojects.has(m.mgroup.mproject) then continue + if not mpackages.has(m.mgroup.mpackage) then continue mmodules.add(m) end @@ -241,7 +241,7 @@ class MProjectDot stream.write("digraph g \{\n") stream.write("rankdir=BT;node[shape=box];\n") # Generate the nodes - for p in model.mprojects do + for p in model.mpackages do dot_cluster(stream, p.root.as(not null)) end # Generate the edges diff --git a/src/model/mproject.nit b/src/model/mpackage.nit similarity index 65% rename from src/model/mproject.nit rename to src/model/mpackage.nit index 283d54c..c1625ee 100644 --- a/src/model/mproject.nit +++ b/src/model/mpackage.nit @@ -12,26 +12,26 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Modelisation of a Nit project -module mproject +# Modelisation of a Nit package +module mpackage import model_base private import more_collections import poset import mdoc -# A Nit project, that encompass a product -class MProject +# A Nit package, that encompass a product +class MPackage super MConcern - # The name of the project + # The name of the package redef var name: String redef fun full_name do return name redef var c_name = name.to_cmangle is lazy - # The model of the project + # The model of the package redef var model: Model # The root of the group tree @@ -44,11 +44,11 @@ class MProject init do - model.mprojects.add(self) - model.mproject_by_name.add_one(name, self) + model.mpackages.add(self) + model.mpackage_by_name.add_one(name, self) end - # MProject are always roots of the concerns hierarchy + # MPackage are always roots of the concerns hierarchy redef fun parent_concern do return null redef fun mdoc_or_fallback @@ -58,16 +58,16 @@ class MProject end end -# A group of modules in a project +# A group of modules in a package class MGroup super MConcern # The name of the group - # empty name for a default group in a single-module project + # empty name for a default group in a single-module package redef var name: String - # The enclosing project - var mproject: MProject + # The enclosing package + var mpackage: MPackage # The parent group if any # see `in_nesting` for more @@ -82,20 +82,20 @@ class MGroup return "{p.full_name}/{name}" end - # The group is the group tree on the project (`mproject.mgroups`) + # The group is the group tree on the package (`mpackage.mgroups`) # nested groups (children) are smaller # nesting group (see `parent`) is bigger var in_nesting: POSetElement[MGroup] is noinit - # Is `self` the root of its project? - fun is_root: Bool do return mproject.root == self + # Is `self` the root of its package? + fun is_root: Bool do return mpackage.root == self # The filepath (usually a directory) of the group, if any var filepath: nullable String = null is writable init do - var tree = mproject.mgroups + var tree = mpackage.mgroups self.in_nesting = tree.add_node(self) var parent = self.parent if parent != null then @@ -103,29 +103,29 @@ class MGroup end end - redef fun model do return mproject.model + redef fun model do return mpackage.model redef fun parent_concern do if not is_root then return parent - return mproject + return mpackage end redef fun to_s do return name end redef class Model - # projects of the model - var mprojects = new Array[MProject] + # packages of the model + var mpackages = new Array[MPackage] - # Collections of project grouped by their names - private var mproject_by_name = new MultiHashMap[String, MProject] + # Collections of package grouped by their names + private var mpackage_by_name = new MultiHashMap[String, MPackage] - # Return all project named `name` - # If such a project is not yet loaded, null is returned (instead of an empty array) - fun get_mprojects_by_name(name: String): nullable Array[MProject] + # Return all package named `name` + # If such a package is not yet loaded, null is returned (instead of an empty array) + fun get_mpackages_by_name(name: String): nullable Array[MPackage] do - if mproject_by_name.has_key(name) then - return mproject_by_name[name] + if mpackage_by_name.has_key(name) then + return mpackage_by_name[name] else return null end diff --git a/src/modelize/modelize_class.nit b/src/modelize/modelize_class.nit index 5fd0381..14c8e94 100644 --- a/src/modelize/modelize_class.nit +++ b/src/modelize/modelize_class.nit @@ -99,11 +99,11 @@ redef class ModelBuilder return end - # Check for conflicting class full-names in the project + # Check for conflicting class full-names in the package if mmodule.mgroup != null and mvisibility >= protected_visibility then var mclasses = model.get_mclasses_by_name(name) if mclasses != null then for other in mclasses do - if other.intro_mmodule.mgroup != null and other.intro_mmodule.mgroup.mproject == mmodule.mgroup.mproject then + if other.intro_mmodule.mgroup != null and other.intro_mmodule.mgroup.mpackage == mmodule.mgroup.mpackage then # Skip classes that are buggy if other.try_intro == null then continue warning(nclassdef, "full-name-conflict", "Error: a class named `{other.full_name}` is already defined in module `{other.intro_mmodule}` at {other.intro.location}.") diff --git a/src/modelize/modelize_property.nit b/src/modelize/modelize_property.nit index 97312f2..eec36f4 100644 --- a/src/modelize/modelize_property.nit +++ b/src/modelize/modelize_property.nit @@ -629,12 +629,12 @@ redef class APropdef return false end - # Check for full-name conflicts in the project. - # A public property should have a unique qualified name `project::class::prop`. + # Check for full-name conflicts in the package. + # A public property should have a unique qualified name `package::class::prop`. if mprop.intro_mclassdef.mmodule.mgroup != null and mprop.visibility >= protected_visibility then var others = modelbuilder.model.get_mproperties_by_name(mprop.name) if others != null then for other in others do - if other != mprop and other.intro_mclassdef.mmodule.mgroup != null and other.intro_mclassdef.mmodule.mgroup.mproject == mprop.intro_mclassdef.mmodule.mgroup.mproject and other.intro_mclassdef.mclass.name == mprop.intro_mclassdef.mclass.name and other.visibility >= protected_visibility then + if other != mprop and other.intro_mclassdef.mmodule.mgroup != null and other.intro_mclassdef.mmodule.mgroup.mpackage == mprop.intro_mclassdef.mmodule.mgroup.mpackage and other.intro_mclassdef.mclass.name == mprop.intro_mclassdef.mclass.name and other.visibility >= protected_visibility then modelbuilder.advice(self, "full-name-conflict", "Warning: A property named `{other.full_name}` is already defined in module `{other.intro_mclassdef.mmodule}` for the class `{other.intro_mclassdef.mclass.name}`.") break end diff --git a/src/neo.nit b/src/neo.nit index 79799e8..c110468 100644 --- a/src/neo.nit +++ b/src/neo.nit @@ -35,15 +35,15 @@ # # Note : All nodes described here are MEntities. # -# `MProject` +# `MPackage` # -# * labels: `MProject`, `model_name` and `MEntity`. -# * `(:MProject)-[:ROOT]->(:MGroup)`: root of the group tree. +# * labels: `MPackage`, `model_name` and `MEntity`. +# * `(:MPackage)-[:ROOT]->(:MGroup)`: root of the group tree. # # `MGroup` # # * labels: `MGroup`, `model_name` and `MEntity`. -# * `(:MGroup)-[:PROJECT]->(:MProject)`: associated project. +# * `(:MGroup)-[:PROJECT]->(:MPackage)`: associated package. # * `(:MGroup)-[:PARENT]->(:MGroup)`: parent group. Does not exist for the root # group. # * `(:MGroup)-[:DECLARES]->(:MModule)`: modules that are direct children of @@ -233,9 +233,9 @@ class NeoModel fun load(model: Model): Model do var nodes: Array[NeoNode] - toolcontext.info("Loading project node...", 1) - nodes = client.nodes_with_labels([model_name, "MProject"]) - for node in nodes do to_mproject(model, node) + toolcontext.info("Loading package node...", 1) + nodes = client.nodes_with_labels([model_name, "MPackage"]) + for node in nodes do to_mpackage(model, node) toolcontext.info("Loading groups...", 1) nodes = client.nodes_with_labels([model_name, "MGroup"]) for node in nodes do to_mgroup(model, node) @@ -304,9 +304,9 @@ class NeoModel # Collect all nodes from the current `model`. private fun collect_model_nodes(model: Model): Collection[NeoNode] do - for mproject in model.mprojects do - to_node(mproject) - for mgroup in mproject.mgroups do to_node(mgroup) + for mpackage in model.mpackages do + to_node(mpackage) + for mgroup in mpackage.mgroups do to_node(mgroup) end return nodes.values end @@ -332,7 +332,7 @@ class NeoModel # `mentities` are stored locally to avoid duplication. fun to_node(mentity: MEntity): NeoNode do if nodes.has_key(mentity) then return nodes[mentity] - if mentity isa MProject then return mproject_node(mentity) + if mentity isa MPackage then return mpackage_node(mentity) if mentity isa MGroup then return mgroup_node(mentity) if mentity isa MModule then return mmodule_node(mentity) if mentity isa MClass then return mclass_node(mentity) @@ -346,7 +346,7 @@ class NeoModel # Get the `MEntity` associated with `node`. fun to_mentity(model: Model, node: NeoNode): MEntity do - if node.labels.has("MProject") then return to_mproject(model, node) + if node.labels.has("MPackage") then return to_mpackage(model, node) if node.labels.has("MGroup") then return to_mgroup(model, node) if node.labels.has("MModule") then return to_mmodule(model, node) if node.labels.has("MClass") then return to_mclass(model, node) @@ -372,30 +372,30 @@ class NeoModel return node end - # Build a `NeoNode` representing `mproject`. - private fun mproject_node(mproject: MProject): NeoNode do - var node = make_node(mproject) - node.labels.add "MProject" - var root = mproject.root + # Build a `NeoNode` representing `mpackage`. + private fun mpackage_node(mpackage: MPackage): NeoNode do + var node = make_node(mpackage) + node.labels.add "MPackage" + var root = mpackage.root if root != null then node.out_edges.add(new NeoEdge(node, "ROOT", to_node(root))) end return node end - # Build a new `MProject` from a `node`. + # Build a new `MPackage` from a `node`. # - # REQUIRE `node.labels.has("MProject")` - private fun to_mproject(model: Model, node: NeoNode): MProject do + # REQUIRE `node.labels.has("MPackage")` + private fun to_mpackage(model: Model, node: NeoNode): MPackage do var m = mentities.get_or_null(node.id.as(Int)) - if m isa MProject then return m + if m isa MPackage then return m - assert node.labels.has("MProject") - var mproject = new MProject(node["name"].to_s, model) - mentities[node.id.as(Int)] = mproject - set_doc(node, mproject) - mproject.root = to_mgroup(model, node.out_nodes("ROOT").first) - return mproject + assert node.labels.has("MPackage") + var mpackage = new MPackage(node["name"].to_s, model) + mentities[node.id.as(Int)] = mpackage + set_doc(node, mpackage) + mpackage.root = to_mgroup(model, node.out_nodes("ROOT").first) + return mpackage end # Build a `NeoNode` representing `mgroup`. @@ -403,7 +403,7 @@ class NeoModel var node = make_node(mgroup) node.labels.add "MGroup" var parent = mgroup.parent - node.out_edges.add(new NeoEdge(node, "PROJECT", to_node(mgroup.mproject))) + node.out_edges.add(new NeoEdge(node, "PROJECT", to_node(mgroup.mpackage))) if parent != null then node.out_edges.add(new NeoEdge(node, "PARENT", to_node(parent))) end @@ -424,13 +424,13 @@ class NeoModel if m isa MGroup then return m assert node.labels.has("MGroup") - var mproject = to_mproject(model, node.out_nodes("PROJECT").first) + var mpackage = to_mpackage(model, node.out_nodes("PROJECT").first) var parent: nullable MGroup = null var out = node.out_nodes("PARENT") if not out.is_empty then parent = to_mgroup(model, out.first) end - var mgroup = new MGroup(node["name"].to_s, mproject, parent) + var mgroup = new MGroup(node["name"].to_s, mpackage, parent) mentities[node.id.as(Int)] = mgroup set_doc(node, mgroup) return mgroup diff --git a/src/nitcatalog.nit b/src/nitcatalog.nit index 6aba6f1..ba0cb1c 100644 --- a/src/nitcatalog.nit +++ b/src/nitcatalog.nit @@ -12,28 +12,28 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Basic catalog generator for Nit projects +# Basic catalog generator for Nit packages # # See: # -# The tool scans projects and generates the HTML files of a catalog. +# The tool scans packages and generates the HTML files of a catalog. # # ## Features # -# * [X] scan projects and their `.ini` -# * [X] generate lists of projects -# * [X] generate a page per project with the readme and most metadata +# * [X] scan packages and their `.ini` +# * [X] generate lists of packages +# * [X] generate a page per package with the readme and most metadata # * [ ] link/include/be included in the documentation -# * [ ] propose `related projects` -# * [ ] show directory content (a la nitls) +# * [ ] propose `related packages` +# * [X] show directory content (a la nitls) # * [X] gather git information from the working directory # * [ ] gather git information from the repository -# * [ ] gather project information from github +# * [ ] gather package information from github # * [ ] gather people information from github # * [ ] reify people # * [ ] separate information gathering from rendering # * [ ] move up information gathering in (existing or new) service modules -# * [ ] add command line options +# * [X] add command line options # * [ ] harden HTML (escaping, path injection, etc) # * [ ] nitcorn server with RESTful API # @@ -48,13 +48,13 @@ # How to use the tool as the basis of a Nit code archive on the web usable with a package manager is not clear. module nitcatalog -import loader # Scan&load projects, groups and modules +import loader # Scan&load packages, groups and modules import doc::doc_down # Display mdoc import md5 # To get gravatar images import counter # For statistics import modelize # To process and count classes and methods -redef class MProject +redef class MPackage # Return the associated metadata from the `ini`, if any fun metadata(key: String): nullable String do @@ -139,7 +139,7 @@ class CatalogPage end redef class Int - # Returns `log(self+1)`. Used to compute score of projects + # Returns `log(self+1)`. Used to compute score of packages fun score: Float do return (self+1).to_f.log end @@ -150,46 +150,46 @@ class Catalog # used to access the files and count source lines of code var modelbuilder: ModelBuilder - # Projects by tag - var tag2proj = new MultiHashMap[String, MProject] + # Packages by tag + var tag2proj = new MultiHashMap[String, MPackage] - # Projects by category - var cat2proj = new MultiHashMap[String, MProject] + # Packages by category + var cat2proj = new MultiHashMap[String, MPackage] - # Projects by maintainer - var maint2proj = new MultiHashMap[String, MProject] + # Packages by maintainer + var maint2proj = new MultiHashMap[String, MPackage] - # Projects by contributors - var contrib2proj = new MultiHashMap[String, MProject] + # Packages by contributors + var contrib2proj = new MultiHashMap[String, MPackage] - # Dependency between projects - var deps = new POSet[MProject] + # Dependency between packages + var deps = new POSet[MPackage] - # Number of modules by project - var mmodules = new Counter[MProject] + # Number of modules by package + var mmodules = new Counter[MPackage] - # Number of classes by project - var mclasses = new Counter[MProject] + # Number of classes by package + var mclasses = new Counter[MPackage] - # Number of methods by project - var mmethods = new Counter[MProject] + # Number of methods by package + var mmethods = new Counter[MPackage] - # Number of line of code by project - var loc = new Counter[MProject] + # Number of line of code by package + var loc = new Counter[MPackage] - # Number of commits by project - var commits = new Counter[MProject] + # Number of commits by package + var commits = new Counter[MPackage] - # Score by project + # Score by package # # The score is loosely computed using other metrics - var score = new Counter[MProject] + var score = new Counter[MPackage] - # Scan, register and add a contributor to a project - fun add_contrib(person: String, mproject: MProject, res: Template) + # Scan, register and add a contributor to a package + fun add_contrib(person: String, mpackage: MPackage, res: Template) do var projs = contrib2proj[person] - if not projs.has(mproject) then projs.add mproject + if not projs.has(mpackage) then projs.add mpackage var name = person var email = null var page = null @@ -238,45 +238,90 @@ class Catalog res.add "" end + # Recursively generate a level in the file tree of the *content* section + private fun gen_content_level(ot: OrderedTree[Object], os: Array[Object], res: Template) + do + res.add "
    \n" + for o in os do + res.add "
  • " + if o isa MGroup then + var d = "" + var mdoc = o.mdoc + if mdoc != null then d = ": {mdoc.html_synopsis.write_to_string}" + res.add "{o.name}{d} ({o.filepath.to_s})" + else if o isa ModulePath then + var d = "" + var m = o.mmodule + if m != null then + var mdoc = m.mdoc + if mdoc != null then d = ": {mdoc.html_synopsis.write_to_string}" + end + res.add "{o.name}{d} ({o.filepath.to_s})" + else + abort + end + var subs = ot.sub.get_or_null(o) + if subs != null then gen_content_level(ot, subs, res) + res.add "
  • \n" + end + res.add "
\n" + end - # Compute information and generate a full HTML page for a project - fun project_page(mproject: MProject): Writable + # Compute information and generate a full HTML page for a package + fun package_page(mpackage: MPackage): Writable do var res = new CatalogPage - var score = score[mproject].to_f - var name = mproject.name.html_escape + var score = score[mpackage].to_f + var name = mpackage.name.html_escape res.more_head.add """{{{name}}}""" res.add """

{{{name}}}

""" - var mdoc = mproject.mdoc_or_fallback + var mdoc = mpackage.mdoc_or_fallback if mdoc != null then score += 100.0 res.add mdoc.html_documentation score += mdoc.content.length.score end + + res.add "

Content

" + var ot = new OrderedTree[Object] + for g in mpackage.mgroups do + var pa = g.parent + if g.is_interesting then + ot.add(pa, g) + pa = g + end + for mp in g.module_paths do + ot.add(pa, mp) + end + end + ot.sort_with(alpha_comparator) + gen_content_level(ot, ot.roots, res) + + res.add """
""" - self.score[mproject] = score.to_i + self.score[mpackage] = score.to_i return res end - # Return a short HTML sequence for a project + # Return a short HTML sequence for a package # # Intended to use in lists. - fun li_project(p: MProject): String + fun li_package(p: MPackage): String do var res = "" var f = "{p.name}.html" @@ -456,14 +503,14 @@ class Catalog return res end - # List projects by group. + # List packages by group. # # For each key of the `map` a `

` is generated. - # Each project is then listed. + # Each package is then listed. # # The list of keys is generated first to allow fast access to the correct `

`. # `id_prefix` is used to give an id to the `

` element. - fun list_by(map: MultiHashMap[String, MProject], id_prefix: String): Template + fun list_by(map: MultiHashMap[String, MPackage], id_prefix: String): Template do var res = new Template var keys = map.keys.to_a @@ -478,7 +525,7 @@ class Catalog res.add "

{e} ({projs.length})

\n
    \n" for p in projs do res.add "
  • " - res.add li_project(p) + res.add li_package(p) res.add "
  • " end res.add "
" @@ -486,8 +533,8 @@ class Catalog return res end - # List the 10 best projects from `cpt` - fun list_best(cpt: Counter[MProject]): Template + # List the 10 best packages from `cpt` + fun list_best(cpt: Counter[MPackage]): Template do var res = new Template res.add "
    " @@ -496,7 +543,7 @@ class Catalog if i > best.length then break var p = best[best.length-i] res.add "
  • " - res.add li_project(p) + res.add li_package(p) # res.add " ({cpt[p]})" res.add "
  • " end @@ -504,10 +551,10 @@ class Catalog return res end - # Collect more information on a project using the `git` tool. - fun git_info(mproject: MProject) + # Collect more information on a package using the `git` tool. + fun git_info(mpackage: MPackage) do - var ini = mproject.ini + var ini = mpackage.ini if ini == null then return # TODO use real git info @@ -515,7 +562,7 @@ class Catalog #var branch = ini.get_or_null("upstream.git.branch") #var directory = ini.get_or_null("upstream.git.directory") - var dirpath = mproject.root.filepath + var dirpath = mpackage.root.filepath if dirpath == null then return # Collect commits info @@ -523,57 +570,61 @@ class Catalog var contributors = new Counter[String] var commits = res.split("\n") if commits.not_empty and commits.last == "" then commits.pop - self.commits[mproject] = commits.length + self.commits[mpackage] = commits.length for l in commits do var s = l.split_once_on(';') if s.length != 2 or s.last == "" then continue # Collect date of last and first commit - if mproject.last_date == null then mproject.last_date = s.first - mproject.first_date = s.first + if mpackage.last_date == null then mpackage.last_date = s.first + mpackage.first_date = s.first # Count contributors contributors.inc(s.last) end for c in contributors.sort.reverse_iterator do - mproject.contributors.add c + mpackage.contributors.add c end end - # Produce a HTML table containig information on the projects + # Produce a HTML table containig information on the packages # - # `project_page` must have been called before so that information is computed. - fun table_projects(mprojects: Array[MProject]): Template + # `package_page` must have been called before so that information is computed. + fun table_packages(mpackages: Array[MPackage]): Template do - alpha_comparator.sort(mprojects) + alpha_comparator.sort(mpackages) var res = new Template res.add "\n" res.add "\n" res.add "\n" res.add "\n" res.add "\n" - res.add "\n" - res.add "\n" - res.add "\n" - res.add "\n" + if deps.not_empty then + res.add "\n" + res.add "\n" + res.add "\n" + res.add "\n" + end res.add "\n" res.add "\n" res.add "\n" res.add "\n" res.add "\n" res.add "" - for p in mprojects do + for p in mpackages do res.add "" res.add "" var maint = "?" if p.maintainers.not_empty then maint = p.maintainers.first res.add "" res.add "" - res.add "" - res.add "" - res.add "" - res.add "" + if deps.not_empty then + res.add "" + res.add "" + res.add "" + res.add "" + end res.add "" res.add "" res.add "" @@ -600,6 +651,13 @@ end var model = new Model var tc = new ToolContext +var opt_dir = new OptionString("Directory where the HTML files are generated", "-d", "--dir") +var opt_no_git = new OptionBool("Do not gather git information from the working directory", "--no-git") +var opt_no_parse = new OptionBool("Do not parse nit files (no importation information)", "--no-parse") +var opt_no_model = new OptionBool("Do not analyse nit files (no class/method information)", "--no-model") + +tc.option_context.add_option(opt_dir, opt_no_git, opt_no_parse, opt_no_model) + tc.process_options(sys.args) tc.keep_going = true @@ -612,31 +670,36 @@ for a in tc.option_context.rest do modelbuilder.identify_file(a) end -# Scan projects and compute information -for p in model.mprojects do +# Scan packages and compute information +for p in model.mpackages do var g = p.root assert g != null modelbuilder.scan_group(g) # Load the module to process importation information + if opt_no_parse.value then continue modelbuilder.parse_group(g) catalog.deps.add_node(p) for gg in p.mgroups do for m in gg.mmodules do for im in m.in_importation.direct_greaters do - var ip = im.mproject + var ip = im.mpackage if ip == null or ip == p then continue catalog.deps.add_edge(p, ip) end end +end +if not opt_no_git.value then for p in model.mpackages do catalog.git_info(p) end # Run phases to modelize classes and properties (so we can count them) -#modelbuilder.run_phases +if not opt_no_model.value then + modelbuilder.run_phases +end -var out = "out" +var out = opt_dir.value or else "catalog.out" out.mkdir # Generate the css (hard coded) @@ -741,31 +804,33 @@ css.write_to_file(out/"style.css") # PAGES -for p in model.mprojects do +for p in model.mpackages do # print p var f = "{p.name}.html" - catalog.project_page(p).write_to_file(out/f) + catalog.package_page(p).write_to_file(out/f) end # INDEX var index = new CatalogPage -index.more_head.add "Projects in Nit" +index.more_head.add "Packages in Nit" index.add """
    -

    Projects in Nit

    +

    Packages in Nit

    """ -index.add "

    Highlighted Projects

    \n" +index.add "

    Highlighted Packages

    \n" index.add catalog.list_best(catalog.score) -index.add "

    Most Required

    \n" -var reqs = new Counter[MProject] -for p in model.mprojects do - reqs[p] = catalog.deps[p].smallers.length - 1 +if catalog.deps.not_empty then + index.add "

    Most Required

    \n" + var reqs = new Counter[MPackage] + for p in model.mpackages do + reqs[p] = catalog.deps[p].smallers.length - 1 + end + index.add catalog.list_best(reqs) end -index.add catalog.list_best(reqs) index.add "

    By First Tag

    \n" index.add catalog.list_by(catalog.cat2proj, "cat_") @@ -778,7 +843,7 @@ index.add """
    namemaintcontribreqsdirect
    reqs
    clientsdirect
    clients
    reqsdirect
    reqs
    clientsdirect
    clients
    modulesclassesmethodslinesscore
    {p.name}{maint}{p.contributors.length}{deps[p].greaters.length-1}{deps[p].direct_greaters.length}{deps[p].smallers.length-1}{deps[p].direct_smallers.length}{deps[p].greaters.length-1}{deps[p].direct_greaters.length}{deps[p].smallers.length-1}{deps[p].direct_smallers.length}{mmodules[p]}{mclasses[p]}{mmethods[p]}