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 <jean@pryen.org>
Reviewed-by: Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=benitlux
tags=network
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=brainfuck
tags=language
maintainer=Lucas Bajolet <r4pass@hotmail.com>
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
-[project]
+[package]
name=crazy_moles
tags=game
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
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
-[project]
+[package]
name=friendz
tags=game
maintainer=Jean Privat <jean@pryen.org>
-[project]
+[package]
name=github_merge
tags=cli
maintainer=Jean Privat <jean@pryen.org>
-[project]
+[package]
name=github_search_for_jni
tags=cli
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=header_keeper
tags=devel,cli
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=inkscape_tools
tags=devel,cli
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
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
-[project]
+[package]
name=jwrapper
tags=java,devel,cli
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
../../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
-[project]
+[package]
name=mnit_test
tags=
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=neo_doxygen
tags=devel,cli
maintainer=Jean-Christophe Beaupré <jcbrinfo@users.noreply.github.com>
-[project]
+[package]
name=nitcc
tags=devel,cli
maintainer=Jean Privat <jean@pryen.org>
-[project]
+[package]
name=nitester
tags=devel,cli
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
wiki.logo=assets/logo.png
wiki.root_dir=.
wiki.rsync_dir=moz-code.org:nitiwiki/
+wiki.highlighter=./highlighter.sh "$1"
--- /dev/null
+#!/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
--- /dev/null
+# 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
+<table class="hello"><tr>
+<td>Hello</td>
+<td>World</td>
+</tr></table>
+~~~
+
+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<br/>
+World
+~~~
-[project]
+[package]
name=nitiwiki
tags=web,cli
maintainer=Alexandre Terrasa <alexandre@moz-code.org>
--- /dev/null
+# 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
module nitiwiki
import wiki_html
+import markdown_highlight
# Locate nit directory
private fun compute_nit_dir(opt_nit_dir: OptionString): String do
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
end
end
-private class NitiwikiDecorator
+# The decorator associated to `MarkdownProcessor`.
+class NitiwikiDecorator
super HTMLDecorator
# Wiki used to resolve links.
-[project]
+[package]
name=nitrpg
tags=devel,web,cli
maintainer=Alexandre Terrasa <alexandre@moz-code.org>
-[project]
+[package]
name=objcwrapper
tags=devel,cli
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=online_ide
tags=devel,web
maintainer=Johan Kayser <johan.kayser@viacesi.fr>
-[project]
+[package]
name=opportunity
tags=web
maintainer=Lucas Bajolet <r4pass@hotmail.com>
-[project]
+[package]
name=pep8analysis
tags=educ,web,cli
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=physical_interface_for_mpd_on_rpi
tags=embedded,cli
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=refund
tags=example,cli
maintainer=Alexandre Terrasa <alexandre@moz-code.org>
-[project]
+[package]
name=rss_downloader
tags=network,cli
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=simplan
tags=ai,example,cli
maintainer=Jean Privat <jean@pryen.org>
-[project]
+[package]
name=sort_downloads
tags=cli
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
../../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/
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"
transform="matrix(0.9571749,0,0,0.9571749,14.241487,126.08446)">
<path
style="font-size:52.50814056px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:-1px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Armalite Rifle;-inkscape-font-specification:Armalite Rifle"
- d="m 258.625,595.8125 c -4.89966,1.4313 -12.56953,-1.70866 -15.1875,4.5625 -0.4775,5.90634 -3.5509,14.50575 2.71875,18.6875 2.28891,1.18746 5.12,1.54986 7.5625,0.59375 0.52227,3.72431 1.0541,7.99473 -2.03125,10.59375 -3.51238,6.69348 3.86364,14.87896 10.90625,12.96875 6.54546,1.2404 16.20527,-0.87285 16.34375,-9 1.15076,-4.65522 -4.58661,-6.69297 -3.46875,-11.1875 -0.95739,-2.94159 3.31489,-1.69978 4.46875,-3.78125 5.83868,-2.11249 5.55685,-9.07334 5.53125,-14.34375 1.81324,-6.47371 -5.8435,-9.85183 -11.15625,-8.5625 -4.34595,0.15294 -9.06169,-1.83389 -13.21875,-0.125 0.0516,-2.21144 -1.36209,-0.68823 -2.46875,-0.40625 z"
+ d="m 258.625,595.8125 c -4.89966,1.4313 -12.56953,-1.70866 -15.1875,4.5625 -0.4775,5.90634 -3.5509,14.50575 2.71875,18.6875 2.28891,1.18746 5.12,1.54986 7.5625,0.59375 0.52227,3.72431 1.0541,7.99473 -2.03125,10.59375 -3.51238,6.69348 3.86364,14.87896 10.90625,12.96875 6.54546,1.2404 16.20527,-0.87285 16.34375,-9 1.15076,-4.65522 0.20769,-5.09487 1.32555,-9.5894 -0.95739,-2.94159 -1.47941,-3.29788 -0.32555,-5.37935 5.83868,-2.11249 5.55685,-9.07334 5.53125,-14.34375 1.81324,-6.47371 -5.8435,-9.85183 -11.15625,-8.5625 -4.34595,0.15294 -9.06169,-1.83389 -13.21875,-0.125 0.0516,-2.21144 -1.36209,-0.68823 -2.46875,-0.40625 z"
id="path3211"
- inkscape:connector-curvature="0" />
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccccccc" />
<path
style="font-size:52.50814056px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:-1px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Armalite Rifle;-inkscape-font-specification:Armalite Rifle"
d="m 286.25,592.6875 c -2.39783,0.63195 -3.74457,2.90332 -6.59375,2.8125 -5.4632,2.29227 -6.35616,10.35289 -2.0625,14.25 -0.60542,4.15669 0.70607,8.39731 0.4375,12.3125 -0.0599,3.57375 -1.98208,6.31549 -3.3125,9.34375 -1.62554,5.38708 2.55698,12.80186 8.96875,10.96875 6.47834,0.22337 16.30714,2.49861 19.125,-5.53125 1.23942,-3.73894 -0.38135,-7.90712 -3.59375,-10.09375 0.3082,-5.37065 -0.71586,-11.3191 0.59375,-16.375 6.74005,-4.69817 1.76294,-18.17585 -6.625,-15.0625 -2.79844,0.69065 -4.06188,-3.31293 -6.9375,-2.625 z"
inkscape:connector-curvature="0" />
<path
style="font-size:52.50814056px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:-1px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Armalite Rifle;-inkscape-font-specification:Armalite Rifle"
- d="m 362.71875,595.53125 c -4.88629,0.1191 -10.06204,0.70685 -14.78125,0.75 -5.47787,-0.76679 -11.36437,-0.40783 -16.78125,-0.15625 -5.17104,2.08849 -5.75771,9.90066 -1.65625,13.3125 -0.73815,5.29915 0.55713,11.35287 -0.28125,16.21875 -1.57391,2.43976 0.0174,5.43494 -1.9375,7.65625 -1.21338,8.01052 8.60308,12.27891 15.15625,10.1875 4.10866,1.15111 8.03361,-0.96492 11.90625,0.75 4.70244,-0.0919 9.41322,-0.76127 13.9375,-1.21875 6.34357,-2.47232 7.27867,-12.62071 1.1875,-15.90625 -2.84504,-3.85906 -6.71699,-8.25024 -7.5,-12.8125 2.57537,-4.33547 10.38664,-3.74912 10.125,-10.0625 0.19504,-4.87459 -4.47645,-9.43549 -9.375,-8.71875 z"
+ d="m 362.71875,595.53125 c -4.88629,0.1191 -10.06204,0.70685 -14.78125,0.75 -5.47787,-0.76679 -11.36437,-0.40783 -16.78125,-0.15625 -5.17104,2.08849 -5.75771,9.90066 -1.65625,13.3125 -0.73815,5.29915 0.55713,11.35287 -0.28125,16.21875 -1.57391,2.43976 0.0174,5.43494 -1.9375,7.65625 -1.21338,8.01052 8.60308,12.27891 15.15625,10.1875 4.10866,1.15111 8.03361,-0.96492 11.90625,0.75 4.70244,-0.0919 9.41322,-0.76127 13.9375,-1.21875 6.34357,-2.47232 7.27867,-12.62071 1.1875,-15.90625 -2.84504,-3.85906 -3.69836,-8.25024 -4.48137,-12.8125 2.57537,-4.33547 7.36801,-3.74912 7.10637,-10.0625 0.19504,-4.87459 -4.47645,-9.43549 -9.375,-8.71875 z"
id="path3217"
- inkscape:connector-curvature="0" />
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccccccc" />
<path
style="font-size:52.50814056px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:-1px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Armalite Rifle;-inkscape-font-specification:Armalite Rifle"
d="m 387.9375,595.15625 c -4.67722,2.02978 -9.78906,-1.62403 -14.46875,1.25 -9.65979,4.02935 -13.06716,17.5954 -7.09375,25.71875 -5.60204,3.65765 -3.86108,11.71823 -2.5625,17.15625 1.89135,4.23664 7.4795,4.74734 11.125,3.125 3.94271,1.07416 7.9082,-0.0824 11.78125,1.1875 12.90654,0.16282 22.05847,-17.35307 13.34375,-27.46875 4.21701,-4.46396 3.58479,-12.34862 1.53125,-17.90625 -3.12179,-4.23683 -8.89538,-1.69513 -13.1875,-3.09375 l -0.46875,0.0312 z"
inkscape:connector-curvature="0" />
<path
style="font-size:52.50814056px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:-1px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Armalite Rifle;-inkscape-font-specification:Armalite Rifle"
- d="m 413.09375,593.625 c -5.989,0.79809 -12.31873,3.77439 -13.59375,10.28125 -2.37552,6.92367 2.58427,13.98287 3.0625,20.28125 -6.66505,6.69348 -1.32209,20.82556 8.75,19.25 7.10297,0.39661 12.84047,-7.75209 9.8125,-14.21875 0.3156,-2.89071 -3.70654,-4.76237 -1.46875,-7.53125 2.44848,-7.39695 6.24638,-18.36454 -1.53125,-23.75 -0.23875,-2.6484 -2.19852,-4.85675 -5.03125,-4.3125 z"
+ d="m 413.09375,593.625 c -5.989,0.79809 -12.31873,3.77439 -13.59375,10.28125 -2.77433,6.83505 1.00514,13.63195 3.0625,20.28125 -6.66505,6.69348 -1.32209,20.82556 8.75,19.25 7.10297,0.39661 12.84047,-7.75209 9.8125,-14.21875 0.3156,-2.89071 -3.70654,-4.76237 -1.46875,-7.53125 2.44848,-7.39695 6.24638,-18.36454 -1.53125,-23.75 -0.23875,-2.6484 -2.19852,-4.85675 -5.03125,-4.3125 z"
id="path3221"
- inkscape:connector-curvature="0" />
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccc" />
</g>
<g
style="stroke:#000000;stroke-width:3.85294461;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
x="251.05626"
id="tspan2996"
sodipodi:role="line">TINKS!</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:50.25947571px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#e6e6e6;fill-opacity:1;stroke:none;font-family:Sans"
+ x="251.05626"
+ y="809.98505"
+ id="text3032"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan3034"
+ x="251.05626"
+ y="809.98505"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;letter-spacing:-0.9571749px;fill:#e6e6e6;fill-opacity:1;font-family:Armalite Rifle;-inkscape-font-specification:Armalite Rifle">TINKS!</tspan></text>
</g>
</g>
</svg>
-[project]
+[package]
name=tinks
tags=game
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=tnitter
tags=web
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=wiringPi
tags=embedded,wrapper
maintainer=Alexandre Terrasa <alexandre@moz-code.org>
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"
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" />
- <text
- xml:space="preserve"
+ <g
style="font-size:269.1137085px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Droid Sans;-inkscape-font-specification:Droid Sans"
- x="299.74573"
- y="770.06946"
- id="text2997"
- sodipodi:linespacing="125%"><tspan
- sodipodi:role="line"
- id="tspan2999"
- x="299.74573"
- y="770.06946">+</tspan></text>
+ id="text2997">
+ <path
+ d="m 364.00188,685.0516 -50.85303,0 0,-19.71047 50.85303,0 0,-51.11584 19.71048,0 0,51.11584 50.85303,0 0,19.71047 -50.85303,0 0,50.59023 -19.71048,0 0,-50.59023"
+ style=""
+ id="path2996" />
+ </g>
<path
inkscape:connector-curvature="0"
id="path3018"
id="path2997"
style="font-size:202.30386353px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Droid Sans;-inkscape-font-specification:Droid Sans"
d="m 179.68975,735.88154 c -1e-5,-2.50244 0.32926,-4.60977 0.98782,-6.32199 0.65852,-1.77805 1.54755,-3.19391 2.66709,-4.2476 1.1195,-1.11949 2.43658,-1.90974 3.95125,-2.37074 1.51462,-0.52681 3.16097,-0.79023 4.93905,-0.79025 1.71218,2e-5 3.32561,0.26344 4.84028,0.79025 1.58047,0.461 2.93048,1.25125 4.05003,2.37074 1.11948,1.05369 2.00851,2.46955 2.66709,4.2476 0.65851,1.71222 0.98778,3.81955 0.98782,6.32199 -4e-5,2.43661 -0.32931,4.54394 -0.98782,6.322 -0.65858,1.71221 -1.54761,3.12807 -2.66709,4.24759 -1.11955,1.11952 -2.46956,1.94269 -4.05003,2.46953 -1.51467,0.52683 -3.1281,0.79024 -4.84028,0.79025 -1.77808,-10e-6 -3.42443,-0.26342 -4.93905,-0.79025 -1.51467,-0.52684 -2.83175,-1.35001 -3.95125,-2.46953 -1.11954,-1.11952 -2.00857,-2.53538 -2.66709,-4.24759 -0.65856,-1.77806 -0.98783,-3.88539 -0.98782,-6.322" />
- <text
- xml:space="preserve"
+ <g
style="font-size:269.1137085px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Droid Sans;-inkscape-font-specification:Droid Sans"
- x="64.031456"
- y="1006.8839"
- id="text3013"
- sodipodi:linespacing="125%"><tspan
- sodipodi:role="line"
- id="tspan3015"
- x="64.031456"
- y="1006.8839">=</tspan></text>
+ id="text3013">
+ <path
+ d="m 77.43458,894.9284 0,-19.57907 121.41654,0 0,19.57907 -121.41654,0 m 0,53.87531 0,-19.71048 121.41654,0 0,19.71048 -121.41654,0"
+ style=""
+ id="path2999" />
+ </g>
</g>
</svg>
-[project]
+[package]
name=calculator
tags=example
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=circular_list
tags=algo,example
maintainer=Jean Privat <jean@pryen.org>
-[project]
+[package]
name=clock
tags=example
maintainer=Jean Privat <jean@pryen.org>
-[project]
+[package]
name=clock_more
tags=example
maintainer=Jean Privat <jean@pryen.org>
-[project]
+[package]
name=draw_operation
tags=
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=extern_methods
tags=wrapper,example
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=fibonacci
tags=example
maintainer=Jean Privat <jean@pryen.org>
-[project]
+[package]
name=hello_world
tags=example
maintainer=Jean Privat <jean@pryen.org>
-[project]
+[package]
name=int_stack
tags=example
maintainer=Jean Privat <jean@pryen.org>
-[project]
+[package]
name=leapfrog
tags=game,terminal
maintainer=Jean Privat <jean@pryen.org>
-default: android
+default: linux
../../contrib/inkscape_tools/bin/svg_to_icons:
$(MAKE) -C ../../contrib/inkscape_tools
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/
-[project]
+[package]
name=mnit_ballz
tags=game
maintainer=Romain Chanoir <romain.chanoir@viacesi.fr>
--- /dev/null
+# 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
# this file is part of NIT ( http://www.nitlanguage.org ).
#
-# Copyright 2014 Romain Chanoir <romain.chanoir@viacesi.fr>
-#
# 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
# 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
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
--- /dev/null
+# 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
--- /dev/null
+# 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
--- /dev/null
+# 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
#this file is part of NIT ( http://www.nitlanguage.org ).
#
-# Copyright 2014 Romain Chanoir <romain.chanoir@viacesi.fr>
-#
# 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
# 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
--- /dev/null
+# 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
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
-[project]
+[package]
name=mnit_dino
tags=game
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=montecarlo
tags=example
maintainer=Jean Privat <jean@pryen.org>
-[project]
+[package]
name=print_arguments
tags=example
maintainer=Jean Privat <jean@pryen.org>
-[project]
+[package]
name=procedural_array
tags=example
maintainer=Jean Privat <jean@pryen.org>
-[project]
+[package]
name=rosettacode
tags=example
maintainer=Jean Privat <jean@pryen.org>
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
-[project]
+[package]
name=shoot
tags=game
maintainer=Jean Privat <jean@pryen.org>
-[project]
+[package]
name=a_star
tags=algo,lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=ai
tags=ai,algo,lib
maintainer=Jean Privat <jean@pryen.org>
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;
}
`}
end
redef class PlayableAudio
- redef init do app.add_to_sounds(self)
+ redef init do add_to_sounds(self)
end
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
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
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.
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
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
# 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
-[project]
+[package]
name=android
tags=platform,lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
#
# ~~~~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
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)
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"
-[project]
+[package]
name=app
tags=lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=array_debug
tags=debug,lib
maintainer=Alexandre Terrasa <alexandre@moz-code.org>
-[project]
+[package]
name=base64
tags=encoding,lib
maintainer=Lucas Bajolet <r4pass@hotmail.com>
-[project]
+[package]
name=bcm2835
tags=embedded,lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=binary
tags=io,lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=bitmap
tags=lib
maintainer=Lucas Bajolet <r4pass@hotmail.com>
-[project]
+[package]
name=bucketed_game
tags=game,lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=buffered_ropes
tags=algo,text,lib
maintainer=Lucas Bajolet <r4pass@hotmail.com>
-[project]
+[package]
name=c
tags=language,wrapper,lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
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
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)
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
-[project]
+[package]
name=cartesian
tags=algo,lib
maintainer=Jean Privat <jean@pryen.org>
-[project]
+[package]
name=cocoa
tags=wrapper,lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=combinations
tags=algo,lib
maintainer=Jean Privat <jean@pryen.org>
-[project]
+[package]
name=console
tags=terminal,lib
maintainer=Jean-Christophe Beaupré <jcbrinfo@users.noreply.github.com>
-[project]
+[package]
name=core
tags=lib
maintainer=Jean Privat <jean@pryen.org>
-[project]
+[package]
name=counter
tags=algo,lib
maintainer=Jean Privat <jean@pryen.org>
-[project]
+[package]
name=cpp
tags=language,wrapper,lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=crypto
tags=crypto,algo,lib
maintainer=Lucas Bajolet <r4pass@hotmail.com>
-[project]
+[package]
name=csv
tags=format,lib
maintainer=Alexandre Terrasa <alexandre@moz-code.org>
-[project]
+[package]
name=curl
tags=network,wrapper,lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=curses
tags=ui,terminal,wrapper,lib
maintainer=Jean Privat <jean@pryen.org>
-[project]
+[package]
name=date
tags=lib
maintainer=Mehdi Ait Younes <overpex@gmail.com>
-[project]
+[package]
name=deriving
tags=lib
maintainer=Jean Privat <jean@pryen.org>
-[project]
+[package]
name=dom
tags=xml,lib
maintainer=Lucas Bajolet <r4pass@hotmail.com>
-[project]
+[package]
name=dummy_array
tags=algo,lib
maintainer=Floréal Morandat <morandat@lirmm.fr>
-[project]
+[package]
name=egl
tags=graphics,wrapper,lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
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; `}
-[project]
+[package]
name=emscripten
tags=platform,lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=filter_stream
tags=io,lib
maintainer=Floréal Morandat <morandat@lirmm.fr>
-[project]
+[package]
name=for_abuse
tags=algo,lib
maintainer=Jean Privat <jean@pryen.org>
--- /dev/null
+# 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
--- /dev/null
+# 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 """<uses-feature android:glEsVersion="0x00020000"/>"""
+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
--- /dev/null
+# 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
--- /dev/null
+# 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
--- /dev/null
+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
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="512"
+ height="512"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.48.5 r10040"
+ sodipodi:docname="New document 1">
+ <defs
+ id="defs4" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.98994949"
+ inkscape:cx="292.54393"
+ inkscape:cy="311.81525"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1279"
+ inkscape:window-height="1379"
+ inkscape:window-x="3840"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-540.36218)">
+ <rect
+ style="fill:#ab00cf;fill-opacity:1;stroke:none"
+ id="rect2985"
+ width="512"
+ height="512"
+ x="0"
+ y="540.36218"
+ ry="69.507881"
+ rx="69.507881" />
+ <path
+ sodipodi:type="star"
+ style="fill:#ff001b;fill-opacity:1;stroke:none"
+ id="path3755"
+ sodipodi:sides="3"
+ sodipodi:cx="22.857143"
+ sodipodi:cy="-299.06638"
+ sodipodi:r1="235.13782"
+ sodipodi:r2="118.85303"
+ sodipodi:arg1="-1.5707963"
+ sodipodi:arg2="-0.52359875"
+ inkscape:flatsided="false"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="m 22.85715,-534.20419 102.92974,175.7113 100.70557,176.99543 -203.63532,1.28411 -203.63532,-1.28412 100.705584,-176.99542 z"
+ inkscape:transform-center-y="-22.453664"
+ transform="translate(232.85714,1144.2857)" />
+ </g>
+</svg>
--- /dev/null
+[package]
+name=triangle
+tags=example
+maintainer=Alexis Laferrière <alexis.laf@xymus.net>
+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
--- /dev/null
+# 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
--- /dev/null
+# 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
# 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
--- /dev/null
+# 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
-[project]
+[package]
name=gamnit
tags=game,lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=geometry
tags=algo,lib
maintainer=Romain Chanoir <romain.chanoir@viacesi.fr>
-[project]
+[package]
name=gettext
tags=i18n,lib
maintainer=Lucas Bajolet <r4pass@hotmail.com>
-[project]
+[package]
name=github
tags=web,lib
maintainer=Alexandre Terrasa <alexandre@moz-code.org>
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
end
import android::aware
+intrude import c
in "C Header" `{
#include <GLES2/gl2.h>
# 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
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_*`
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
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
#
# 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);
`}
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);
# 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
-[project]
+[package]
name=glesv2
tags=graphics,wrapper,lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=graphs
tags=algo,lib
maintainer=Alexandre Blondin Massé <alexandre.blondin.masse@gmail.com>
-[project]
+[package]
name=gtk
tags=ui,wrapper,lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=hash_debug
tags=debug,lib
maintainer=Jean Privat <jean@pryen.org>
-[project]
+[package]
name=html
tags=format,lib
maintainer=Alexandre Terrasa <alexandre@moz-code.org>
-[project]
+[package]
name=ini
tags=format,lib
maintainer=Alexandre Terrasa <alexandre@moz-code.org>
-[project]
+[package]
name=ios
tags=wrapper,lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=java
tags=java,wrapper,lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=json
tags=format,lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=jvm
tags=java,wrapper,lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=libevent
tags=wrapper,lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
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
-[project]
+[package]
name=linux
tags=lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
end
redef fun add_code(v, block) do
- if block isa BlockFence and block.meta != null then
- v.add "<pre class=\"{block.meta.to_s}\"><code>"
+ var meta = block.meta
+ if meta != null then
+ v.add "<pre class=\""
+ append_value(v, meta)
+ v.add "\"><code>"
else
v.add "<pre><code>"
end
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.
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.
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
-[project]
+[package]
name=markdown
tags=format,lib
maintainer=Alexandre Terrasa <alexandre@moz-code.org>
-[project]
+[package]
name=md5
tags=encoding,lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=meta
tags=lib
maintainer=Jean Privat <jean@pryen.org>
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
-[project]
+[package]
name=mnit
tags=lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=mongodb
tags=database,lib
maintainer=Alexandre Terrasa <alexandre@moz-code.org>
-[project]
+[package]
name=more_collections
tags=algo,lib
maintainer=Jean Privat <jean@pryen.org>
-[project]
+[package]
name=mpd
tags=sound,lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=mpi
tags=parallelism,lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=neo4j
tags=database,lib
maintainer=Alexandre Terrasa <alexandre@moz-code.org>
-[project]
+[package]
name=nitcc_runtime
tags=lib
maintainer=Jean Privat <jean@pryen.org>
-[project]
+[package]
name=nitcorn
tags=network,lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=niti_runtime
tags=lib
maintainer=Jean Privat <jean@pryen.org>
-[project]
+[package]
name=noise
tags=algo,lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=opts
tags=cli,lib
maintainer=Jean Privat <jean@pryen.org>
-[project]
+[package]
name=ordered_tree
tags=algo,lib
maintainer=Jean Privat <jean@pryen.org>
-[project]
+[package]
name=parser_base
tags=format,lib
maintainer=Lucas Bajolet <r4pass@hotmail.com>
-[project]
+[package]
name=perfect_hashing
tags=algo,lib
maintainer=Julien Pagès <julien.projet@gmail.com>
-[project]
+[package]
name=performance_analysis
tags=debug,lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=pipeline
tags=algo,lib
maintainer=Jean Privat <jean@pryen.org>
-[project]
+[package]
name=pnacl
tags=platform,lib
maintainer=Johan Kayser <johan.kayser@viacesi.fr>
-[project]
+[package]
name=poset
tags=algo,lib
maintainer=Jean Privat <jean@pryen.org>
-[project]
+[package]
name=posix_ext
tags=wrapper,lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=privileges
tags=lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=progression
tags=lib
maintainer=Jean-Christophe Beaupré <jcbrinfo@users.noreply.github.com>
-[project]
+[package]
name=pthreads
tags=parallelism,wrapper,lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=realtime
tags=lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=ropes_debug
tags=debug,lib
maintainer=Lucas Bajolet <r4pass@hotmail.com>
-[project]
+[package]
name=sax
tags=xml,format,lib
maintainer=Jean-Christophe Beaupré <jcbrinfo@users.noreply.github.com>
-[project]
+[package]
name=saxophonit
tags=xml,format,lib
maintainer=Jean-Christophe Beaupré <jcbrinfo@users.noreply.github.com>
-[project]
+[package]
name=scene2d
tags=game,lib
maintainer=Jean Privat <jean@pryen.org>
-[project]
+[package]
name=sdl
tags=graphics,wrapper,lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=sdl2
tags=graphics,wrapper,lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=sendmail
tags=network,lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=serialization
tags=lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=sexp
tags=format,lib
maintainer=Lucas Bajolet <r4pass@hotmail.com>
-[project]
+[package]
name=sha1
tags=encoding,lib
maintainer=Lucas Bajolet <r4pass@hotmail.com>
-[project]
+[package]
name=signals
tags=wrapper,lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=socket
tags=network,lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=sqlite3
tags=database,lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=standard
tags=lib
maintainer=Jean Privat <jean@pryen.org>
-[project]
+[package]
name=symbol
tags=lib
maintainer=Jean Privat <jean@pryen.org>
-[project]
+[package]
name=template
tags=lib
maintainer=Jean Privat <jean@pryen.org>
-[project]
+[package]
name=test_suite
tags=devel,lib
maintainer=Alexandre Terrasa <alexandre@moz-code.org>
-[project]
+[package]
name=trees
tags=algo,lib
maintainer=Alexandre Terrasa <alexandre@moz-code.org>
-[project]
+[package]
name=websocket
tags=network,lib
maintainer=Lucas Bajolet <r4pass@hotmail.com>
-[project]
+[package]
name=x11
tags=ui,lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
-[project]
+[package]
name=xdg_basedir
tags=wrapper,lib
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
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
# NAME
-nitls - lists the projects, groups and paths of Nit sources files.
+nitls - lists the packages, groups and paths of Nit sources files.
# SYNOPSIS
# 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.
$ 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
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
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.
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("\}")
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("\}")
# Returns the mentity name with short signature.
#
- # * MProject: `foo`
+ # * MPackage: `foo`
# * MGroup: `foo`
# * MModule: `foo`
# * MClass: `Foo[E]`
# 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]`
# 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`
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
# 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
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
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
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 "<pre class=\"{meta}\"><code>"
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 "<pre class=\"{meta}\"><code>"
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.
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
# 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]
# 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
# 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
#
# 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
end
end
-redef class MProject
+redef class MPackage
redef fun mentities_by_namespace(namespace, res) do lookup_in(mgroups, namespace, res)
end
# 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.
#
# 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
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
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
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
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
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
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
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
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
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
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
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)
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")
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)
redef var is_hidden = false
end
-# The main project article.
+# The main package article.
class HomeArticle
super DocArticle
end
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
# Returns the mentity name without short signature.
#
- # * MProject: `foo`
+ # * MPackage: `foo`
# * MGroup: `foo`
# * MModule: `foo`
# * MClass: `Foo[E]`
# 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]`
# 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`
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
# 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
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 "::<span>"
tpl.add html_link
tpl.add "</span>"
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
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
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
#
# 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.
# 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)
# 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
# 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.
#
# * 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
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
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
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)
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
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)
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}.")
# 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
# 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)
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
# 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:
## 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)
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
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
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
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
buf.append("<html>\n<body>\n")
buf.append("<h1>Model</h1>\n")
- buf.append("<h2>Projects</h2>\n")
- for mproject in model.mprojects do
- buf.append("<h3 id='project-{mproject}'>Project {mproject}</h3>\n")
+ buf.append("<h2>Packages</h2>\n")
+ for mpackage in model.mpackages do
+ buf.append("<h3 id='package-{mpackage}'>Package {mpackage}</h3>\n")
buf.append("<dl>\n")
buf.append("<dt>groups</dt>\n")
- for x in mproject.mgroups do
+ for x in mpackage.mgroups do
buf.append("<dd>{linkto(x)}</dd>\n")
end
buf.append("</dl>\n")
end
buf.append("<h2>Groups</h2>\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("<h3 id='group-{mgroup}'>Group {mgroup}</h3>\n")
buf.append("<dl>\n")
- buf.append("<dt>project</dt>\n")
- buf.append("<dd>{linkto(mproject)}</dd>\n")
+ buf.append("<dt>package</dt>\n")
+ buf.append("<dd>{linkto(mpackage)}</dd>\n")
buf.append("<dt>filepath</dt>\n")
buf.append("<dd>{mgroup.filepath.to_s}</dd>\n")
var p = mgroup.parent
private fun linkto(o: Object): String
do
- if o isa MProject then
- return "<a href='#project-{o}'>{o}</a>"
+ if o isa MPackage then
+ return "<a href='#package-{o}'>{o}</a>"
else if o isa MGroup then
return "<a href='#group-{o}'>{o}</a>"
else if o isa MModule then
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
# 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
#
module mmodule
import location
-import mproject
+import mpackage
private import more_collections
# The container class of a Nit object-oriented model.
# 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
# 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
if mgroup == null then
return full_name
else
- return mgroup.mproject.full_name
+ return mgroup.mpackage.full_name
end
end
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
if mgroup == null then
return c_name
else
- return mgroup.mproject.c_name
+ return mgroup.mpackage.c_name
end
end
# 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}"
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}"
# 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
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 "::"
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
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
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
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
# 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
# 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]
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
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
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
# 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
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
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
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
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
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}.")
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
#
# 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
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)
# 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
# `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)
# 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)
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`.
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
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
# 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: <http://nitlanguage.org/catalog/>
#
-# 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
#
# 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
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
# 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
res.add "</li>"
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 "<ul>\n"
+ for o in os do
+ res.add "<li>"
+ if o isa MGroup then
+ var d = ""
+ var mdoc = o.mdoc
+ if mdoc != null then d = ": {mdoc.html_synopsis.write_to_string}"
+ res.add "<strong>{o.name}</strong>{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 "<strong>{o.name}</strong>{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 "</li>\n"
+ end
+ res.add "</ul>\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 """<title>{{{name}}}</title>"""
res.add """
<div class="content">
<h1 class="package-name">{{{name}}}</h1>
"""
- 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 "<h2>Content</h2>"
+ 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 """
</div>
<div class="sidebar">
<ul class="box">
"""
- var homepage = mproject.metadata("upstream.homepage")
+ var homepage = mpackage.metadata("upstream.homepage")
if homepage != null then
score += 5.0
var e = homepage.html_escape
res.add "<li><a href=\"{e}\">{e}</a></li>\n"
end
- var maintainer = mproject.metadata("project.maintainer")
+ var maintainer = mpackage.metadata("package.maintainer")
if maintainer != null then
score += 5.0
- add_contrib(maintainer, mproject, res)
- mproject.maintainers.add maintainer
+ add_contrib(maintainer, mpackage, res)
+ mpackage.maintainers.add maintainer
var projs = maint2proj[maintainer]
- if not projs.has(mproject) then projs.add mproject
+ if not projs.has(mpackage) then projs.add mpackage
end
- var license = mproject.metadata("project.license")
+ var license = mpackage.metadata("package.license")
if license != null then
score += 5.0
var e = license.html_escape
res.add "</ul>\n"
res.add "<h3>Source Code</h3>\n<ul class=\"box\">\n"
- var browse = mproject.metadata("upstream.browse")
+ var browse = mpackage.metadata("upstream.browse")
if browse != null then
score += 5.0
var e = browse.html_escape
res.add "<li><a href=\"{e}\">{e}</a></li>\n"
end
- var git = mproject.metadata("upstream.git")
+ var git = mpackage.metadata("upstream.git")
if git != null then
var e = git.html_escape
res.add "<li><tt>{e}</tt></li>\n"
end
- var last_date = mproject.last_date
+ var last_date = mpackage.last_date
if last_date != null then
var e = last_date.html_escape
res.add "<li>most recent commit: {e}</li>\n"
end
- var first_date = mproject.first_date
+ var first_date = mpackage.first_date
if first_date != null then
var e = first_date.html_escape
res.add "<li>oldest commit: {e}</li>\n"
end
- var commits = commits[mproject]
+ var commits = commits[mpackage]
if commits != 0 then
res.add "<li>{commits} commits</li>\n"
end
res.add "</ul>\n"
res.add "<h3>Tags</h3>\n"
- var tags = mproject.metadata("project.tags")
+ var tags = mpackage.metadata("package.tags")
var ts2 = new Array[String]
var cat = null
if tags != null then
t = t.trim
if t == "" then continue
if cat == null then cat = t
- tag2proj[t].add mproject
+ tag2proj[t].add mpackage
t = t.html_escape
ts2.add "<a href=\"index.html#tag_{t}\">{t}</a>"
end
if ts2.is_empty then
var t = "none"
cat = t
- tag2proj[t].add mproject
+ tag2proj[t].add mpackage
res.add "<a href=\"index.html#tag_{t}\">{t}</a>"
end
- if cat != null then cat2proj[cat].add mproject
+ if cat != null then cat2proj[cat].add mpackage
score += ts2.length.score
- var reqs = deps[mproject].greaters.to_a
- reqs.remove(mproject)
- alpha_comparator.sort(reqs)
- res.add "<h3>Requirements</h3>\n"
- if reqs.is_empty then
- res.add "none"
- else
- var list = new Array[String]
- for r in reqs do
- var direct = deps.has_direct_edge(mproject, r)
- var s = "<a href=\"{r}.html\">"
- if direct then s += "<strong>"
- s += r.to_s
- if direct then s += "</strong>"
- s += "</a>"
- list.add s
+ if deps.has(mpackage) then
+ var reqs = deps[mpackage].greaters.to_a
+ reqs.remove(mpackage)
+ alpha_comparator.sort(reqs)
+ res.add "<h3>Requirements</h3>\n"
+ if reqs.is_empty then
+ res.add "none"
+ else
+ var list = new Array[String]
+ for r in reqs do
+ var direct = deps.has_direct_edge(mpackage, r)
+ var s = "<a href=\"{r}.html\">"
+ if direct then s += "<strong>"
+ s += r.to_s
+ if direct then s += "</strong>"
+ s += "</a>"
+ list.add s
+ end
+ res.add_list(list, ", ", " and ")
end
- res.add_list(list, ", ", " and ")
- end
- reqs = deps[mproject].smallers.to_a
- reqs.remove(mproject)
- alpha_comparator.sort(reqs)
- res.add "<h3>Clients</h3>\n"
- if reqs.is_empty then
- res.add "none"
- else
- var list = new Array[String]
- for r in reqs do
- var direct = deps.has_direct_edge(r, mproject)
- var s = "<a href=\"{r}.html\">"
- if direct then s += "<strong>"
- s += r.to_s
- if direct then s += "</strong>"
- s += "</a>"
- list.add s
+ reqs = deps[mpackage].smallers.to_a
+ reqs.remove(mpackage)
+ alpha_comparator.sort(reqs)
+ res.add "<h3>Clients</h3>\n"
+ if reqs.is_empty then
+ res.add "none"
+ else
+ var list = new Array[String]
+ for r in reqs do
+ var direct = deps.has_direct_edge(r, mpackage)
+ var s = "<a href=\"{r}.html\">"
+ if direct then s += "<strong>"
+ s += r.to_s
+ if direct then s += "</strong>"
+ s += "</a>"
+ list.add s
+ end
+ res.add_list(list, ", ", " and ")
end
- res.add_list(list, ", ", " and ")
- end
- score += deps[mproject].greaters.length.score
- score += deps[mproject].direct_greaters.length.score
- score += deps[mproject].smallers.length.score
- score += deps[mproject].direct_smallers.length.score
+ score += deps[mpackage].greaters.length.score
+ score += deps[mpackage].direct_greaters.length.score
+ score += deps[mpackage].smallers.length.score
+ score += deps[mpackage].direct_smallers.length.score
+ end
- var contributors = mproject.contributors
+ var contributors = mpackage.contributors
if not contributors.is_empty then
res.add "<h3>Contributors</h3>\n<ul class=\"box\">"
for c in contributors do
- add_contrib(c, mproject, res)
+ add_contrib(c, mpackage, res)
end
res.add "</ul>"
end
var mclasses = 0
var mmethods = 0
var loc = 0
- for g in mproject.mgroups do
+ for g in mpackage.mgroups do
mmodules += g.module_paths.length
for m in g.mmodules do
var am = modelbuilder.mmodule2node(m)
end
end
end
- self.mmodules[mproject] = mmodules
- self.mclasses[mproject] = mclasses
- self.mmethods[mproject] = mmethods
- self.loc[mproject] = loc
+ self.mmodules[mpackage] = mmodules
+ self.mclasses[mpackage] = mclasses
+ self.mmethods[mpackage] = mmethods
+ self.loc[mpackage] = loc
#score += mmodules.score
score += mclasses.score
res.add """
</div>
"""
- 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"
return res
end
- # List projects by group.
+ # List packages by group.
#
# For each key of the `map` a `<h3>` 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 `<h3>`.
# `id_prefix` is used to give an id to the `<h3>` 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
res.add "<h3 id=\"{id_prefix}{e}\">{e} ({projs.length})</h3>\n<ul>\n"
for p in projs do
res.add "<li>"
- res.add li_project(p)
+ res.add li_package(p)
res.add "</li>"
end
res.add "</ul>"
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 "<ul>"
if i > best.length then break
var p = best[best.length-i]
res.add "<li>"
- res.add li_project(p)
+ res.add li_package(p)
# res.add " ({cpt[p]})"
res.add "</li>"
end
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
#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
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 "<table data-toggle=\"table\" data-sort-name=\"name\" data-sort-order=\"desc\" width=\"100%\">\n"
res.add "<thead><tr>\n"
res.add "<th data-field=\"name\" data-sortable=\"true\">name</th>\n"
res.add "<th data-field=\"maint\" data-sortable=\"true\">maint</th>\n"
res.add "<th data-field=\"contrib\" data-sortable=\"true\">contrib</th>\n"
- res.add "<th data-field=\"reqs\" data-sortable=\"true\">reqs</th>\n"
- res.add "<th data-field=\"dreqs\" data-sortable=\"true\">direct<br>reqs</th>\n"
- res.add "<th data-field=\"cli\" data-sortable=\"true\">clients</th>\n"
- res.add "<th data-field=\"dcli\" data-sortable=\"true\">direct<br>clients</th>\n"
+ if deps.not_empty then
+ res.add "<th data-field=\"reqs\" data-sortable=\"true\">reqs</th>\n"
+ res.add "<th data-field=\"dreqs\" data-sortable=\"true\">direct<br>reqs</th>\n"
+ res.add "<th data-field=\"cli\" data-sortable=\"true\">clients</th>\n"
+ res.add "<th data-field=\"dcli\" data-sortable=\"true\">direct<br>clients</th>\n"
+ end
res.add "<th data-field=\"mod\" data-sortable=\"true\">modules</th>\n"
res.add "<th data-field=\"cla\" data-sortable=\"true\">classes</th>\n"
res.add "<th data-field=\"met\" data-sortable=\"true\">methods</th>\n"
res.add "<th data-field=\"loc\" data-sortable=\"true\">lines</th>\n"
res.add "<th data-field=\"score\" data-sortable=\"true\">score</th>\n"
res.add "</tr></thead>"
- for p in mprojects do
+ for p in mpackages do
res.add "<tr>"
res.add "<td><a href=\"{p.name}.html\">{p.name}</a></td>"
var maint = "?"
if p.maintainers.not_empty then maint = p.maintainers.first
res.add "<td>{maint}</td>"
res.add "<td>{p.contributors.length}</td>"
- res.add "<td>{deps[p].greaters.length-1}</td>"
- res.add "<td>{deps[p].direct_greaters.length}</td>"
- res.add "<td>{deps[p].smallers.length-1}</td>"
- res.add "<td>{deps[p].direct_smallers.length}</td>"
+ if deps.not_empty then
+ res.add "<td>{deps[p].greaters.length-1}</td>"
+ res.add "<td>{deps[p].direct_greaters.length}</td>"
+ res.add "<td>{deps[p].smallers.length-1}</td>"
+ res.add "<td>{deps[p].direct_smallers.length}</td>"
+ end
res.add "<td>{mmodules[p]}</td>"
res.add "<td>{mclasses[p]}</td>"
res.add "<td>{mmethods[p]}</td>"
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
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)
# 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 "<title>Projects in Nit</title>"
+index.more_head.add "<title>Packages in Nit</title>"
index.add """
<div class="content">
-<h1>Projects in Nit</h1>
+<h1>Packages in Nit</h1>
"""
-index.add "<h2>Highlighted Projects</h2>\n"
+index.add "<h2>Highlighted Packages</h2>\n"
index.add catalog.list_best(catalog.score)
-index.add "<h2>Most Required</h2>\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 "<h2>Most Required</h2>\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 "<h2>By First Tag</h2>\n"
index.add catalog.list_by(catalog.cat2proj, "cat_")
<div class="sidebar">
<h3>Stats</h3>
<ul class="box">
-<li>{{{model.mprojects.length}}} projects</li>
+<li>{{{model.mpackages.length}}} packages</li>
<li>{{{catalog.maint2proj.length}}} maintainers</li>
<li>{{{catalog.contrib2proj.length}}} contributors</li>
<li>{{{catalog.tag2proj.length}}} tags</li>
page.more_head.add "<title>Projets of Nit</title>"
page.add """<div class="content">\n<h1>People of Nit</h1>\n"""
page.add "<h2>Table of Projets</h2>\n"
-page.add catalog.table_projects(model.mprojects)
+page.add catalog.table_packages(model.mpackages)
page.add "</div>\n"
page.write_to_file(out/"table.html")
if o.mmodule != null and not o.mmodule.in_importation.direct_greaters.is_empty then
var ms = new Array[String]
for m in o.mmodule.in_importation.direct_greaters do
- if m.mgroup.mproject == o.mmodule.mgroup.mproject then
+ if m.mgroup.mpackage == o.mmodule.mgroup.mpackage then
ms.add m.name
else
ms.add m.full_name
var opt_keep = new OptionBool("Ignore errors and files that are not a Nit source file", "-k", "--keep")
var opt_recursive = new OptionBool("Process directories recussively", "-r", "--recursive")
-var opt_tree = new OptionBool("List source files in their groups and projects", "-t", "--tree")
+var opt_tree = new OptionBool("List source files in their groups and packages", "-t", "--tree")
var opt_source = new OptionBool("List source files", "-s", "--source")
-var opt_project = new OptionBool("List projects paths (default)", "-P", "--project")
+var opt_package = new OptionBool("List packages paths (default)", "-P", "--package")
var opt_depends = new OptionBool("List dependencies of given modules", "-d", "--depends")
var opt_make = new OptionBool("List dependencies suitable for a rule in a Makefile. Alias for -d, -p and -s", "-M")
var opt_paths = new OptionBool("List only path (instead of name + path)", "-p", "--path")
-tc.option_context.add_option(opt_keep, opt_recursive, opt_tree, opt_source, opt_project, opt_depends, opt_paths, opt_make)
-tc.tooldescription = "Usage: nitls [OPTION]... <file.nit|directory>...\nLists the projects and/or paths of Nit sources files."
+tc.option_context.add_option(opt_keep, opt_recursive, opt_tree, opt_source, opt_package, opt_depends, opt_paths, opt_make)
+tc.tooldescription = "Usage: nitls [OPTION]... <file.nit|directory>...\nLists the packages and/or paths of Nit sources files."
tc.accept_no_arguments = true
tc.process_options(args)
opt_source.value = true
end
-var sum = opt_tree.value.to_i + opt_source.value.to_i + opt_project.value.to_i
+var sum = opt_tree.value.to_i + opt_source.value.to_i + opt_package.value.to_i
if sum > 1 then
- print "Error: options --tree, --source, and --project are exclusive."
+ print "Error: options --tree, --source, and --package are exclusive."
print tc.tooldescription
exit 1
end
-if sum == 0 then opt_project.value = true
+if sum == 0 then opt_package.value = true
tc.keep_going = opt_keep.value
var model = new Model
end
if sum == 0 then
- # If one of the file is a group, default is `opt_tree` instead of `opt_project`
+ # If one of the file is a group, default is `opt_tree` instead of `opt_package`
for a in files do
var g = mb.get_mgroup(a)
if g != null then
opt_tree.value = true
- opt_project.value = false
+ opt_package.value = false
break
end
end
for a in files do
var g = mb.get_mgroup(a)
var mp = mb.identify_file(a)
- if g != null and not opt_project.value then
+ if g != null and not opt_package.value then
mb.scan_group(g)
end
if g == null and mp == null then
var fs = a.files
for f in fs do
g = mb.get_mgroup(a/f)
- if g != null and not opt_project.value then
+ if g != null and not opt_package.value then
mb.scan_group(g)
end
mp = mb.identify_file(a/f)
var sorter = new AlphaEntityComparator
if opt_tree.value then
ot.opt_paths = opt_paths.value
- for p in model.mprojects do
+ for p in model.mpackages do
for g in p.mgroups do
var pa = g.parent
if g.is_interesting then
if opt_source.value then
var list = new Array[ModulePath]
- for p in model.mprojects do
+ for p in model.mpackages do
for g in p.mgroups do
for mp in g.module_paths do
list.add mp
end
end
-if opt_project.value then
+if opt_package.value then
var list = new Array[MGroup]
- for p in model.mprojects do
+ for p in model.mpackages do
list.add p.root.as(not null)
end
sorter.sort(list)
var opt_dir: OptionString = new OptionString("Output directory", "--dir")
# Depth of the visit and generation
- var opt_depth = new OptionEnum(["module", "group", "project"],
+ var opt_depth = new OptionEnum(["module", "group", "package"],
"Depth of the visit and generation", 0, "-d", "--depth")
redef init
modelbuilder.scan_group mgroup
target_modules = mgroup.mmodules
else if toolcontext.opt_depth.value == 2 then
- # project
+ # package
target_modules = new Array[MModule]
importations = new Array[MModule]
if mgroup != null then
- for g in mgroup.mproject.mgroups do
+ for g in mgroup.mpackage.mgroups do
target_modules.add_all g.mmodules
end
-[project]
+[package]
name=nitc
tags=devel,cli
maintainer=Jean Privat <jean@pryen.org>
# The starting quad (`::`)
var n_quad: nullable TQuad = null is writable
- # The list of quad-separated project/group identifiers
+ # The list of quad-separated package/group identifiers
var n_path = new ANodes[TId](self)
# The final module identifier
# The starting quad (`::`)
var n_quad: nullable TQuad = null is writable
- # The list of quad-separated project/group/module identifiers
+ # The list of quad-separated package/group/module identifiers
var n_id = new ANodes[TId](self)
# A class identifier
# Copy assets, resources and libs where expected by the SDK
var project_root = "."
- var mproject = compiler.mainmodule.first_real_mmodule.mproject
- if mproject != null then
- var root = mproject.root
+ var mpackage = compiler.mainmodule.first_real_mmodule.mpackage
+ if mpackage != null then
+ var root = mpackage.root
if root != null then
var filepath = root.filepath
if filepath != null then
var tsa_server= "TSA_SERVER".environ
if key_alias.is_empty then
- toolcontext.error(null,
- "Error: the environment variable `KEY_ALIAS` must be set to use the `--release` option on Android projects.")
+ toolcontext.warning(null, "key-alias",
+ "Warning: the environment variable `KEY_ALIAS` is not set, the APK file will not be signed.")
+
+ # Just move the unsigned APK to outname
+ args = ["mv", apk_path, outname]
+ toolcontext.exec_and_check(args, "Android project error")
return
end
+ # We have a key_alias, try to sign the APK
args = ["jarsigner", "-sigalg", "MD5withRSA", "-digestalg", "SHA1", apk_path, key_alias]
## Use a custom keystore
# Compare model
var sorter = new MEntityNameSorter
-print "# mprojects:"
-var org_mprojects = org_model.mprojects.to_a
-sorter.sort org_mprojects
-print org_mprojects.join(" ")
+print "# mpackages:"
+var org_mpackages = org_model.mpackages.to_a
+sorter.sort org_mpackages
+print org_mpackages.join(" ")
print "------------------------------------"
-var neo_mprojects = neo_model.mprojects.to_a
-sorter.sort neo_mprojects
-print neo_mprojects.join(" ")
+var neo_mpackages = neo_model.mpackages.to_a
+sorter.sort neo_mpackages
+print neo_mpackages.join(" ")
print "\n# mmodules:"
var org_mmodules = org_model.mmodules.to_a
do
print "It works"
var model = modelbuilder.model
- print "I have {model.mprojects.length} projects"
+ print "I have {model.mpackages.length} packages"
print "I have {model.mmodules.length} modules"
var mclasses = mainmodule.flatten_mclass_hierarchy
print "I have {mclasses.length} classes"
var executor: NitUnitExecutor
redef fun add_code(v, block) do
- var code = code_from_block(block)
- var meta = "nit"
- if block isa BlockFence and block.meta != null then
- meta = block.meta.to_s
- end
+ var code = block.raw_content
+ var meta = block.meta or else "nit"
# Do not try to test non-nit code.
if meta != "nit" then return
# Try to parse code blocks
# Add it to the file
executor.blocks.last.append code
end
-
- # Extracts code as String from a `BlockCode`.
- 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
# A unit-test to run
# usualy, only the original module must be imported in the unit test.
var o = mmodule
var g = o.mgroup
- if g != null and g.mproject.name == "core" then
+ if g != null and g.mpackage.name == "core" then
# except for a unit test in a module of `core`
# in this case, the whole `core` must be imported
- o = get_mmodule_by_name(nmodule, g, g.mproject.name).as(not null)
+ o = get_mmodule_by_name(nmodule, g, g.mpackage.name).as(not null)
end
ts.attr("package", mmodule.full_name)
return sys.program_name.basename
end
- # The identified root directory of the Nit project
+ # The identified root directory of the Nit package
var nit_dir: String is noinit
private fun compute_nit_dir: String
#
# $ nitls --[TAB][TAB]
# --bash-toolname --keep --path --tree
-# --depends --log --project --verbose
+# --depends --log --package --verbose
# --disable-phase --log-dir --quiet --version
# --gen-bash-completion --no-color --recursive --warn
# --help --only-metamodel --source
-nitiwiki --config ../contrib/nitiwiki/tests/wiki1/config2.ini --clean --status
-nitiwiki --config ../contrib/nitiwiki/tests/wiki1/config2.ini --clean --render -v
+--config ../contrib/nitiwiki/tests/wiki1/config2.ini --clean --status
+--config ../contrib/nitiwiki/tests/wiki1/config2.ini --clean --render -v ; rm -r ../contrib/nitiwiki/tests/wiki1/out/
fatal error: 'endian.h' file not found
Error: package `glesv1_cm` unknown by `pkg-config`, make sure the development package is be installed
Error: package `glesv2` unknown by `pkg-config`, make sure the development package is be installed
+Error: package `egl` unknown by `pkg-config`, make sure the development package is be installed
fatal error: 'libintl.h' file not found
--- /dev/null
+../lib/mnit/linux/linux_app.nit:29,16--31: Redef Error: a virtual type cannot be refined.
+../lib/mnit/linux/linux_app.nit:30,16--29: Redef Error: a virtual type cannot be refined.
OverviewPage Overview
# home.article
- ## projects.section
+ ## packages.section
### test_prog.definition
ReadmePage test_prog
MGroup: 4 (2.19%)
MVirtualTypeDef: 1 (0.54%)
MVirtualTypeProp: 1 (0.54%)
- MProject: 1 (0.54%)
+ MPackage: 1 (0.54%)
quicksearch-list.js
# MModules metrics
- ## project base_simple3
+ ## package base_simple3
`- group base_simple3
mnoa: number of ancestor modules
avg: 0.0
# MClasses metrics
- ## project base_simple3
+ ## package base_simple3
`- group base_simple3
cnoa: number of ancestor classes
avg: 0.0
min: Object (0)
std: 0.926
sum: 6
-generating project_hierarchy.dot
+generating package_hierarchy.dot
generating module_hierarchy.dot
# Inheritance metrics
- ## project base_simple3
+ ## package base_simple3
`- group base_simple3
cnoac: number of class_kind ancestor
avg: 0.0
# Nullable metrics
- ## project base_simple3
+ ## package base_simple3
`- group base_simple3
cnba: number of accessible attributes (inherited + local)
avg: 0.0
model.html
module_hierarchy.dot
nullables/
-project_hierarchy.dot
+package_hierarchy.dot
rta/
\e[1m\e[32mP\e[m\e[m \e[1m\e[34mbase_simple3\e[m\e[m
\e[1m\e[30mbase_simple3\e[m\e[m
- project base_simple3
+ package base_simple3
\e[30mbase_simple3.nit:17,1--66,13\e[m
\e[1m\e[32mG\e[m\e[m \e[1m\e[34mbase_simple3\e[m\e[m
-# mprojects:
+# mpackages:
test_prog
------------------------------------
test_prog
It works
-I have 1 projects
+I have 1 packages
I have 1 modules
I have 7 classes
For 7 definitions of classes