From: Jean Privat Date: Wed, 22 Apr 2015 04:18:41 +0000 (+0700) Subject: Merge: share/man: Update man for `nitpretty` X-Git-Tag: v0.7.4~11 X-Git-Url: http://nitlanguage.org?hp=23c262b884898a8405a969d833b3a96b74796249 Merge: share/man: Update man for `nitpretty` Fixes #1130 Pull-Request: #1290 Reviewed-by: Alexis Laferrière Reviewed-by: Jean Privat --- diff --git a/contrib/inkscape_tools/README.md b/contrib/inkscape_tools/README.md index 017ec86..c338656 100644 --- a/contrib/inkscape_tools/README.md +++ b/contrib/inkscape_tools/README.md @@ -1,25 +1,28 @@ # SVG to PNG and Nit -This tool is used in combination with Inkscape to simplify assets creation for _mnit_ apps. It uses Inkscape to extract a PNG file from a SVG file. It will also create a Nit source file to create _mnit_ images for each objects with an id beginning by 0. +This tool uses Inkscape to prepare assets for Nit applications from a single SVG file. +It selects objects to extract from the SVG file when their id begins with `0`. -# Features +It will produce two files: -* Creates a sinlge PNG file per SVG source file -* Creates subimages for objects with an id beginning by 0. -* If the id ends with 0 to 9, will instead create an array of subimages. +* A Nit source file that declares a single class with an attribute for each selected object. + The attribute usually holds a single texture, except if the the id ends with a digit, then it will be an array. -# Usage +* A single PNG image file that contains all the selected objects. + With the option `--pow2`, the image size is rounded to the next of 2. + +## Usage 1. Create a new Inkscape document. -2. Create objects and set their ids to begin with 0 -3. Save the document (ex: to `drawing.svg`) the name of the file is important +2. Create objects and set their ids to begin with `0`. +3. Save the document to `drawing.svg` (for this example), the name of the file is used to name the Nit class. 4. Execute `bin/svg_to_png_and_nit drawing.svg` -5. From your code, import the generated source file (at src/drawing.nit`) +5. From your code, import the generated source file at `src/drawing.nit`. 6. Use the class `DrawingImages` and its attributes. -# Examples +## Examples -The minimal test in tests/app/ shows the basic usage of this tool. +The minimal test in `tests/app/` shows the basic usage of this tool. The Dino example `../../../../examples/mnit_dino` also uses this tool and is a more complete and practical example. diff --git a/contrib/inkscape_tools/src/svg_to_png_and_nit.nit b/contrib/inkscape_tools/src/svg_to_png_and_nit.nit index b24cbf5..f9e690b 100644 --- a/contrib/inkscape_tools/src/svg_to_png_and_nit.nit +++ b/contrib/inkscape_tools/src/svg_to_png_and_nit.nit @@ -1,6 +1,6 @@ # This file is part of NIT ( http://www.nitlanguage.org ). # -# Copyright 2012-2014 Alexis Laferrière +# Copyright 2012-2015 Alexis Laferrière # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -14,51 +14,140 @@ # See the License for the specific language governing permissions and # limitations under the License. -# This script extracts pngs from a single svg for all objects with ids -# beginning by 0. Requires Inkscape. +# Extract images of objects from an SVG file using Inkscape module svg_to_png_and_nit import opts import template +# Image information extracted from the SVG file class Image + # Name extracted from the object ID minus the `0` prefix and Nit safe var name: String + + # Left border var x: Int + + # Top border var y: Int + + # Image width var w: Int + + # Image height var h: Int + + # Right border fun right: Int do return x+w + + # Bottom border fun bottom: Int do return y+h redef fun to_s do return name end -# The Nit source file to retreive all images -class ImageSetSrc +# Document being processed, concerns both the source and the target +class Document + # Name of the source file + var drawing_name: String + + # Name of the class to generate + var nit_class_name: String = drawing_name.capitalized + "Images" is lazy + + # Scaling to apply to the exported image + var scale: Float + + # Source minimum X + var min_x: Int + + # Source maximum X + var max_x: Int + + # Source minimum Y + var min_y: Int + + # Source maximum Y + var max_y: Int + + # Get the coordinates for `image` as `"x, y, w, h"` + fun coordinates(image: Image): String + do + var x = image.x.adapt(min_x, scale) + var y = image.y.adapt(min_y, scale) + var w = (image.w.to_f*scale).to_i + var h = (image.h.to_f*scale).to_i + + return "{x}, {y}, {w}, {h}" + end +end + +# Nit module with a single class to retrieve to access the extracted images +abstract class ImageSetSrc super Template - var name: String - init(name: String) do self.name = name + # Target document + var document: Document - var attributes = new Array[String] - var load_exprs = new Array[String] + # Images found in the source document + var images: Array[Image] +end + +# Nit module targeting the MNit framework +class MnitImageSetSrc + super ImageSetSrc redef fun rendering do + # Known array of images + var arrays_of_images = new Array[String] + + # Attributes of the generated class + var attributes = new Array[String] + + # Statements for the generated `load_all` method + var load_exprs = new Array[String] + + # Add images to Nit source file + for image in images do + # Adapt coordinates to new top left and scale + var coordinates = document.coordinates(image) + + var nit_name = image.name + var last_char = nit_name.chars.last + if last_char.to_s.is_numeric then + # Array of images + # TODO support more than 10 images in an array + + nit_name = nit_name.substring(0, nit_name.length-1) + if not arrays_of_images.has(nit_name) then + # Create class attribute to store Array + arrays_of_images.add(nit_name) + attributes.add "\tvar {nit_name} = new Array[Image]\n" + end + load_exprs.add "\t\t{nit_name}.add(main_image.subimage({coordinates}))\n" + else + # Single image + attributes.add "\tvar {nit_name}: Image is noinit\n" + load_exprs.add "\t\t{nit_name} = main_image.subimage({coordinates})\n" + end + end + add """ -# file generated by svg_to_png, do not modify, redef instead +# File generated by svg_to_png_and_nit, do not modify, redef instead import mnit::image_set -class {{{name}}} +class {{{document.nit_class_name}}} super ImageSet + private var main_image: Image is noinit """ add_all attributes add """ redef fun load_all(app: App) do + main_image = app.load_image(\"images/{{{document.drawing_name}}}.png\") """ add_all load_exprs add """ @@ -68,13 +157,94 @@ end end end +# Nit module targeting the Gamnit framework +# +# Gamnit's `Texture` already manage the lazy loading, no need to do it here. +class GamnitImageSetSrc + super ImageSetSrc + + private fun attributes: Array[String] + do + # Separate the images from the arrays of images + var single_images = new Array[Image] + var arrays_of_images = new HashMap[String, Array[Image]] + + for image in images do + var nit_name = image.name + var last_char = nit_name.chars.last + if last_char.to_s.is_numeric then + + # Is an array + nit_name = nit_name.substring(0, nit_name.length-1) + if not arrays_of_images.keys.has(nit_name) then + # Create a new array + var array = new Array[Image] + arrays_of_images[nit_name] = array + end + + arrays_of_images[nit_name].add image + else + # Is a single image + single_images.add image + end + end + + # Attributes of the class + var attributes = new Array[String] + attributes.add "\tprivate var main_image = new Texture(\"images/{document.drawing_name}.png\")\n" + + # Add single images to Nit source file + for image in single_images do + # Adapt coordinates to new top left and scale + var coordinates = document.coordinates(image) + + attributes.add "\tvar {image.name}: Texture = main_image.subtexture({coordinates})\n" + end + + # Add array of images too + for name, images in arrays_of_images do + + var lines = new Array[String] + for image in images do + var coordinates = document.coordinates(image) + lines.add "\t\tmain_image.subtexture({coordinates})" + end + + attributes.add """ + var {{{name}}} = new Array[Texture].with_items( +{{{lines.join(",\n")}}}) +""" + end + + return attributes + end + + redef fun rendering + do + add """ +# File generated by svg_to_png_and_nit, do not modify, redef instead + +import gamnit::display + +class {{{document.nit_class_name}}} + +""" + add_all attributes + add """ +end +""" + end +end + redef class Int - fun adapt(d: Int, scale: Float): Int + # Magic adaption of this coordinates to the given `margin` and `scale` + fun adapt(margin: Int, scale: Float): Int do - var corrected = self-d + var corrected = self-margin return (corrected.to_f*scale).to_i end + # The first power of to equal or greater than `self` fun next_pow2: Int do var p = 2 @@ -83,13 +253,15 @@ redef class Int end end -var opt_out_src = new OptionString("Path to output source file", "--src", "-s") +var opt_out_src = new OptionString("Path to output source file (folder or file)", "--src", "-s") var opt_assets = new OptionString("Path to assert dir where to put PNG files", "--assets", "-a") -var opt_scale = new OptionFloat("Apply scaling to exported images (defaut at 1.0 of 90dpi)", 1.0, "--scale", "-x") +var opt_scale = new OptionFloat("Apply scaling to exported images (default at 1.0 of 90dpi)", 1.0, "--scale", "-x") +var opt_gamnit = new OptionBool("Target the Gamnit framework (by default it targets Mnit)", "--gamnit", "-g") +var opt_pow2 = new OptionBool("Round the image size to the next power of 2", "--pow2") var opt_help = new OptionBool("Print this help message", "--help", "-h") var opt_context = new OptionContext -opt_context.add_option(opt_out_src, opt_assets, opt_scale, opt_help) +opt_context.add_option(opt_out_src, opt_assets, opt_scale, opt_gamnit, opt_pow2, opt_help) opt_context.parse(args) var rest = opt_context.rest @@ -125,15 +297,13 @@ end var src_path = opt_out_src.value if src_path == null then src_path = "src" -if not src_path.file_exists then +if not src_path.file_exists and src_path.file_extension != "nit" then stderr.write "Source dir '{src_path}' does not exist (use --src)\n" exit 1 end var scale = opt_scale.value -var arrays_of_images = new Array[String] - for drawing in drawings do var drawing_name = drawing.basename(".svg") @@ -177,7 +347,7 @@ for drawing in drawings do while not proc.eof do var line = proc.read_line var words = line.split(",") - + if words.length == 5 then var id = words[0] @@ -202,54 +372,37 @@ for drawing in drawings do end proc.close - # Nit class - var nit_class_name = drawing_name.chars.first.to_s.to_upper + drawing_name.substring_from(1) + "Images" - var nit_src = new ImageSetSrc(nit_class_name) - nit_src.attributes.add "\tprivate var main_image: Image is noinit\n" - nit_src.load_exprs.add "\t\tmain_image = app.load_image(\"images/{drawing_name}.png\")\n" # Sort images by name, it prevents Array errors and looks better alpha_comparator.sort(images) - # Add images to Nit source file - for image in images do - # Adapt coordinates to new top left and scale - var x = image.x.adapt(min_x, scale) - var y = image.y.adapt(min_y, scale) - var w = (image.w.to_f*scale).to_i - var h = (image.h.to_f*scale).to_i + var document = new Document(drawing_name, scale, min_x, max_x, min_y, max_y) - var nit_name = image.name - var last_char = nit_name.chars.last - if last_char.to_s.is_numeric then - # Array of images - # TODO support more than 10 images in an array - - nit_name = nit_name.substring(0, nit_name.length-1) - if not arrays_of_images.has(nit_name) then - # Create class attribute to store Array - arrays_of_images.add(nit_name) - nit_src.attributes.add "\tvar {nit_name} = new Array[Image]\n" - end - nit_src.load_exprs.add "\t\t{nit_name}.add(main_image.subimage({x}, {y}, {w}, {h}))\n" - else - # Single image - nit_src.attributes.add "\tvar {nit_name}: Image is noinit\n" - nit_src.load_exprs.add "\t\t{nit_name} = main_image.subimage({x}, {y}, {w}, {h})\n" - end + # Nit class + var nit_src: ImageSetSrc + if opt_gamnit.value then + nit_src = new GamnitImageSetSrc(document, images) + else + nit_src = new MnitImageSetSrc(document, images) + end + + if not src_path.file_extension == "nit" then + src_path = src_path/drawing_name+".nit" end # Output source file - var src_file = new FileWriter.open("{src_path}/{drawing_name}.nit") + var src_file = new FileWriter.open(src_path) nit_src.write_to(src_file) src_file.close - # Find closest power of 2 - var dx = max_x - min_x - max_x = dx.next_pow2 + min_x + # Find next power of 2 + if opt_pow2.value then + var dx = max_x - min_x + max_x = dx.next_pow2 + min_x - var dy = max_y - min_y - max_y = dy.next_pow2 + min_y + var dy = max_y - min_y + max_y = dy.next_pow2 + min_y + end # Inkscape's --export-area inverts the Y axis. It uses the lower left corner of # the drawing area where as queries return coordinates from the top left. diff --git a/contrib/nitrpg/README.md b/contrib/nitrpg/README.md new file mode 100644 index 0000000..c91c77e --- /dev/null +++ b/contrib/nitrpg/README.md @@ -0,0 +1,84 @@ +# Welcome to NitRPG! + +NitRPG is a Role Playing Game that takes place on [GitHub](https://github.com/). + +In NitRPG, GitHub users are represented by players that battle on repo for +nitcoins and glory. + +## Features + +* Auto-update with GitHub hooks +* Display repo statistics +* Display players statsitics +* Repo actions are rewarded by nitcoins +* Players can unlock achievements + +## How to install + +From the `nit` root: + +~~~bash +> cd contrib/nitrpg +> make +~~~ + +### Configuring the GitHub hook + +NitRPG needs you to add a new GitHub hook on your repo to keep the game +`listener` up-to-date automatically. + +Hook configuration: + +* **Payload URL**: URL and port to the listener (ex: `http://yourdomain.com:8080`) +* **Content type**: `application/json` +* **Wich events**: `Send me everything` + +Be sure to set the hook as `Active` in the GitHub admin panel. + +### Starting the listener + +The `listener` program is used to listen to GitHub hooks and update game data. +It should alwaysd be up if you want your game to be kept up-to-date. + +To run the listener: + + ./listener + +The arguments `host` and `port` must correspond to what you entered in your +GitHub hook settings. + +### Starting the web server + +The `web` program act as a [nitcorn](http://nitlanguage.org/doc/stdlib/module_nitcorn__nitcorn.html) webserver that display the game results live. + +To run the webserver: + + ./web + +The arguments `host` and `port` must correspond to what you entered in your +GitHub hook settings. +The `root` argument is used to specify the path from the domain url to the +NitRPG root. + +For example, if NitRPG is installed in `yourdomain.com/nitrpg`: + + ./web localhost 3000 "/nitrpg" + +Leave it empty if NitRPG is installed at the root of the domain: + + ./web localhost 3000 "" + +The webserver can then be accessed at `http://yourdomain.com:3000/nitrpg/`. + +## RoadMap + +NitRPG stills under heavy development. +Incomming features contain (but are not limited to): + +* Periodized stats (weekly, monthly, yearly, overall) +* Display graphs with stats +* More achievements +* Shop: exchange Nitcoins against glorifying items + +You can suggest new achievements or ideas in the +[NitRPG RoadMap Issue](https://github.com/privat/nit/issues/1161). diff --git a/contrib/nitrpg/src/achievements.nit b/contrib/nitrpg/src/achievements.nit index 625bfc2..eeae17e 100644 --- a/contrib/nitrpg/src/achievements.nit +++ b/contrib/nitrpg/src/achievements.nit @@ -400,3 +400,119 @@ class Player10KCommits redef var reward = 10000 redef var threshold = 10000 end + +##################### +### Issue Comments +##################### + +# Unlock achievement after X issue comments. +# +# Used to factorize behavior. +abstract class PlayerXComments + super AchievementReactor + + # Number of comments required to unlock the achievement. + var threshold: Int is noinit + + redef fun react_event(game, event) do + if not event isa IssueCommentEvent then return + if not event.action == "created" then return + var player = event.comment.user.player(game) + if player.stats["comments"] == threshold then + var a = new_achievement(game) + player.unlock_achievement(a, event) + end + end +end + +# Player author his first comment in issues. +class Player1Comment + super PlayerXComments + + redef var id = "player_1_comment" + redef var name = "From lurker to member" + redef var desc = "Comment on an issue." + redef var reward = 10 + redef var threshold = 1 +end + +# Player author 100 issue comments. +class Player100Comments + super PlayerXComments + + redef var id = "player_100_comments" + redef var name = "Chatter" + redef var desc = "Comment 100 times on issues." + redef var reward = 100 + redef var threshold = 100 +end + +# Player author 1000 issue comments. +class Player1KComments + super PlayerXComments + + redef var id = "player_1000__comments" + redef var name = "You sir, talk a lot!" + redef var desc = "Comment 1000 times on issues." + redef var reward = 1000 + redef var threshold = 1000 +end + +# Ping @privat in a comment. +class PlayerPingGod + super AchievementReactor + + redef var id = "player_ping_god" + redef var name = "Ping god" + redef var desc = "Ping the owner of the repo for the first time." + redef var reward = 50 + + redef fun react_event(game, event) do + if not event isa IssueCommentEvent then return + var owner = game.repo.owner.login + if event.comment.body.has("@{owner}".to_re) then + var player = event.comment.user.player(game) + var a = new_achievement(game) + player.unlock_achievement(a, event) + end + end +end + +# Give your first +1 +class PlayerFirstReview + super AchievementReactor + + redef var id = "player_first_review" + redef var name = "First +1" + redef var desc = "Give a +1 for the first time." + redef var reward = 10 + + redef fun react_event(game, event) do + if not event isa IssueCommentEvent then return + # FIXME use a more precise way to locate reviews + if event.comment.has_ok_review then + var player = event.comment.user.player(game) + var a = new_achievement(game) + player.unlock_achievement(a, event) + end + end +end + +# Talk about nitcoin in issue comments. +class PlayerSaysNitcoin + super AchievementReactor + + redef var id = "player_says_nitcoin" + redef var name = "Talking about money" + redef var desc = "Say something about nitcoins in a comment." + redef var reward = 10 + + redef fun react_event(game, event) do + if not event isa IssueCommentEvent then return + if event.comment.body.has("(n|N)itcoin".to_re) then + var player = event.comment.user.player(game) + var a = new_achievement(game) + player.unlock_achievement(a, event) + end + end +end diff --git a/contrib/nitrpg/src/game.nit b/contrib/nitrpg/src/game.nit index 4d62283..d1dff3e 100644 --- a/contrib/nitrpg/src/game.nit +++ b/contrib/nitrpg/src/game.nit @@ -292,6 +292,19 @@ end # utils +# Sort games by descending number of players. +# +# The first in the list is the game with the more players. +class GamePlayersComparator + super Comparator + + redef type COMPARED: Game + + redef fun compare(a, b) do + return b.load_players.length <=> a.load_players.length + end +end + # Sort players by descending number of nitcoins. # # The first in the list is the player with the more of nitcoins. diff --git a/contrib/nitrpg/src/listener.nit b/contrib/nitrpg/src/listener.nit index 0e4ba00..8bee99b 100644 --- a/contrib/nitrpg/src/listener.nit +++ b/contrib/nitrpg/src/listener.nit @@ -63,6 +63,8 @@ l.add_reactor(new Player1Issue, new Player100Issues, new Player1KIssues) l.add_reactor(new Player1Pull, new Player100Pulls, new Player1KPulls) l.add_reactor(new Player1Commit, new Player100Commits, new Player1KCommits) l.add_reactor(new IssueAboutNitdoc, new IssueAboutFFI) +l.add_reactor(new Player1Comment, new Player100Comments, new Player1KComments) +l.add_reactor(new PlayerPingGod, new PlayerFirstReview, new PlayerSaysNitcoin) print "Listening events on {host}:{port}" l.listen diff --git a/contrib/nitrpg/src/statistics.nit b/contrib/nitrpg/src/statistics.nit index dfdb3ba..7b493c6 100644 --- a/contrib/nitrpg/src/statistics.nit +++ b/contrib/nitrpg/src/statistics.nit @@ -187,3 +187,27 @@ redef class PullRequestEvent end end end + +redef class IssueCommentEvent + + # Count posted comments + redef fun react_stats_event(game) do + if action == "created" then + var player = comment.user.player(game) + game.stats.inc("comments") + player.stats.inc("comments") + # FIXME use a more precise way to locate reviews + if comment.has_ok_review then + game.stats.inc("reviews") + player.stats.inc("reviews") + end + game.save + player.save + end + end +end + +redef class IssueComment + # Does this comment contain a "+1"? + fun has_ok_review: Bool do return body.has("\\+1\\b".to_re) +end diff --git a/contrib/nitrpg/src/templates/panels.nit b/contrib/nitrpg/src/templates/panels.nit index 14538c5..e4e7f8f 100644 --- a/contrib/nitrpg/src/templates/panels.nit +++ b/contrib/nitrpg/src/templates/panels.nit @@ -18,6 +18,7 @@ module panels import templates_events +import markdown # A panel can be displayed in a html page. # @@ -98,6 +99,86 @@ class ErrorPanel end +# A panel that display a markdown content rendered as HTML. +class MDPanel + super Panel + + # Markdown text to display. + var text: String + + redef fun rendering do + add """
+
{{{text.md_to_html}}}
+
""" + end +end + +# Display a list of active game. +# +# Used for NitRPG homepage. +class GamesShortListPanel + super Panel + + # Root url used for links. + var root_url: String + + # List of NitRPG games to display. + var games: Array[Game] + + redef fun render_title do + add "  " + add "Active games" + end + + redef fun render_body do + if games.is_empty then + add "No game yet..." + return + end + var sorted = games.to_a + (new GamePlayersComparator).sort(sorted) + for game in sorted do + add "{game.link} ({game.load_players.length} players)
" + end + end +end + +# A panel that display a list of player in a repo. +class GamesListPanel + super GamesShortListPanel + super TablePanel + + redef fun render_title do + add "  " + add "Active games" + end + + redef fun render_body do + if games.is_empty then + add "
" + add "No player yet..." + add "
" + return + end + var sorted = games.to_a + (new GamePlayersComparator).sort(sorted) + add """ + + + + + """ + for game in sorted do + add "" + add " " + add " " + add " " + add "" + end + add "
GamePlayersAchievements
{game.link}{game.load_players.length}{game.load_achievements.length}
" + end +end + # A panel that display repo statistics. class GameStatusPanel super Panel diff --git a/contrib/nitrpg/src/web.nit b/contrib/nitrpg/src/web.nit index b27c457..5f4992e 100644 --- a/contrib/nitrpg/src/web.nit +++ b/contrib/nitrpg/src/web.nit @@ -53,6 +53,79 @@ class RpgAction rsp.body = page.write_to_string return rsp end + + # Returns the game with `name` or null if no game exists with this name. + fun load_game(name: String): nullable Game do + var repo = api.load_repo(name) + if api.was_error or repo == null then return null + var game = new Game(api, repo) + game.root_url = root_url + return game + end + + # Returns the list of saved games from NitRPG data. + fun load_games: Array[Game] do + var res = new Array[Game] + var rpgdir = "nitrpg_data" + if not rpgdir.file_exists then return res + for user in rpgdir.files do + for repo in "{rpgdir}/{user}".files do + var game = load_game("{user}/{repo}") + if game != null then res.add game + end + end + return res + end +end + +# Repo overview page. +class RpgHome + super RpgAction + + # Response page stub. + var page: NitRpgPage is noinit + + redef fun answer(request, url) do + var readme = load_readme + var games = load_games + var response = new HttpResponse(200) + page = new NitRpgPage(root_url) + page.side_panels.add new GamesShortListPanel(root_url, games) + page.flow_panels.add new MDPanel(readme) + response.body = page.write_to_string + return response + end + + # Load the string content of the nitrpg readme file. + private fun load_readme: String do + var readme = "README.md" + if not readme.file_exists then + return "Unable to locate README file." + end + var file = new FileReader.open(readme) + var text = file.read_all + file.close + return text + end +end + +# Display the list of active game. +class ListGames + super RpgAction + + # Response page stub. + var page: NitRpgPage is noinit + + redef fun answer(request, url) do + var games = load_games + var response = new HttpResponse(200) + page = new NitRpgPage(root_url) + page.breadcrumbs = new Breadcrumbs + page.breadcrumbs.add_link(root_url / "games", "games") + page.flow_panels.add new GamesListPanel(root_url, games) + response.body = page.write_to_string + return response + end end # An action that require a game. @@ -72,16 +145,15 @@ class GameAction var owner = request.param("owner") var repo_name = request.param("repo") if owner == null or repo_name == null then - var msg = "Bad request: should look like /repos/:owner/:repo." + var msg = "Bad request: should look like /games/:owner/:repo." return bad_request(msg) end - var repo = new Repo(api, "{owner}/{repo_name}") - game = new Game(api, repo) - game.root_url = root_url - if api.was_error then + var game = load_game("{owner}/{repo_name}") + if game == null then var msg = api.last_error.message return bad_request("Repo Error: {msg}") end + self.game = game var response = new HttpResponse(200) page = new NitRpgPage(root_url) page.side_panels.add new GameStatusPanel(game) @@ -103,6 +175,11 @@ class GameAction # From where to start the display of events related lists. var list_from = 0 + + # TODO should also check 201, 203 ... + private fun is_response_error(response: HttpResponse): Bool do + return response.status_code != 200 + end end # Repo overview page. @@ -111,6 +188,7 @@ class RepoHome redef fun answer(request, url) do var rsp = prepare_response(request, url) + if is_response_error(rsp) then return rsp page.side_panels.add new ShortListPlayersPanel(game) page.flow_panels.add new PodiumPanel(game) page.flow_panels.add new EventListPanel(game, list_limit, list_from) @@ -126,6 +204,7 @@ class ListPlayers redef fun answer(request, url) do var rsp = prepare_response(request, url) + if is_response_error(rsp) then return rsp page.breadcrumbs.add_link(game.url / "players", "players") page.flow_panels.add new ListPlayersPanel(game) rsp.body = page.write_to_string @@ -139,6 +218,7 @@ class PlayerHome redef fun answer(request, url) do var rsp = prepare_response(request, url) + if is_response_error(rsp) then return rsp var name = request.param("player") if name == null then var msg = "Bad request: should look like /:owner/:repo/:players/:name." @@ -166,6 +246,7 @@ class ListAchievements redef fun answer(request, url) do var rsp = prepare_response(request, url) + if is_response_error(rsp) then return rsp page.breadcrumbs.add_link(game.url / "achievements", "achievements") page.flow_panels.add new AchievementsListPanel(game) rsp.body = page.write_to_string @@ -179,6 +260,7 @@ class AchievementHome redef fun answer(request, url) do var rsp = prepare_response(request, url) + if is_response_error(rsp) then return rsp var name = request.param("achievement") if name == null then var msg = "Bad request: should look like /:owner/:repo/achievements/:achievement." @@ -217,6 +299,8 @@ vh.routes.add new Route("/games/:owner/:repo/players", new ListPlayers(root)) vh.routes.add new Route("/games/:owner/:repo/achievements/:achievement", new AchievementHome(root)) vh.routes.add new Route("/games/:owner/:repo/achievements", new ListAchievements(root)) vh.routes.add new Route("/games/:owner/:repo", new RepoHome(root)) +vh.routes.add new Route("/games", new ListGames(root)) +vh.routes.add new Route("/", new RpgHome(root)) var fac = new HttpFactory.and_libevent fac.config.virtual_hosts.add vh diff --git a/src/doc/doc_phases/doc_html.nit b/src/doc/doc_phases/doc_html.nit index 83b02f9..ef74992 100644 --- a/src/doc/doc_phases/doc_html.nit +++ b/src/doc/doc_phases/doc_html.nit @@ -244,7 +244,7 @@ redef class OverviewPage var ssection = new TplSection.with_title("projects", "Projects") for mproject in mprojects do var sarticle = mproject.tpl_article - sarticle.subtitle = mproject.tpl_declaration + sarticle.subtitle = mproject.html_declaration sarticle.content = mproject.tpl_definition var mdoc = mproject.mdoc_or_fallback if mdoc != null then @@ -278,18 +278,18 @@ redef class SearchPage tpl.title = "Index" # modules list for mmodule in modules_list(v, doc) do - tpl.modules.add mmodule.tpl_link + tpl.modules.add mmodule.html_link end # classes list for mclass in classes_list(v, doc) do - tpl.classes.add mclass.tpl_link + tpl.classes.add mclass.html_link end # properties list for mproperty in mprops_list(v, doc) do var m = new Template - m.add mproperty.intro.tpl_link + m.add mproperty.intro.html_link m.add " (" - m.add mproperty.intro.mclassdef.mclass.tpl_link + m.add mproperty.intro.mclassdef.mclass.html_link m.add ")" tpl.props.add m end @@ -369,7 +369,7 @@ redef class MGroupPage end var lnk = new Template lnk.add new TplLabel.with_classes(classes) - lnk.add def.tpl_link + lnk.add def.html_link return new TplListItem.with_content(lnk) end end @@ -410,7 +410,7 @@ redef class MModulePage end var lnk = new Template lnk.add new TplLabel.with_classes(classes) - lnk.add def.tpl_link + lnk.add def.html_link return new TplListItem.with_content(lnk) end end @@ -467,7 +467,7 @@ redef class MClassPage end var lnk = new Template lnk.add new TplLabel.with_classes(classes) - lnk.add mprop.tpl_anchor + lnk.add mprop.html_link_to_anchor return new TplListItem.with_content(lnk) end @@ -496,7 +496,7 @@ end redef class MPropertyPage redef fun init_title(v, doc) do - title = "{mentity.html_name}{mentity.tpl_signature.write_to_string}" + title = "{mentity.html_name}{mentity.html_short_signature.write_to_string}" end redef fun init_topmenu(v, doc) do @@ -527,14 +527,14 @@ redef class DocRoot var section = new TplSection("top") var mentity = page.mentity section.title = mentity.html_name - section.subtitle = mentity.tpl_declaration + section.subtitle = mentity.html_declaration # FIXME ugly hack to avoid diff if mentity isa MGroup and mentity.is_root then section.title = mentity.mproject.html_name - section.subtitle = mentity.mproject.tpl_declaration + section.subtitle = mentity.mproject.html_declaration else if mentity isa MProperty then - section.title = "{mentity.html_name}{mentity.intro.tpl_signature.write_to_string}" - section.subtitle = mentity.tpl_namespace + section.title = "{mentity.html_name}{mentity.intro.html_signature.write_to_string}" + section.subtitle = mentity.html_namespace section.summary_title = mentity.html_name end render(v, doc, page, section) @@ -575,14 +575,14 @@ redef class ConcernSection title.add "from " section.summary_title = "from {mmodule.html_name}" end - title.add mmodule.tpl_namespace + title.add mmodule.html_namespace section.title = title end private fun render_concern_other(page: MEntityPage, section: TplSection, mmodule: MModule) do var title = new Template title.add "in " - title.add mmodule.tpl_namespace + title.add mmodule.html_namespace section.title = title section.summary_title = "in {mmodule.html_name}" end @@ -605,11 +605,11 @@ redef class IntroArticle else if mentity isa MPropDef then article.source_link = v.tpl_showsource(mentity.location) end - # article.subtitle = mentity.tpl_declaration + # article.subtitle = mentity.html_declaration # FIXME diff hack if mentity isa MProperty then # intro title - var ns = mentity.intro.mclassdef.mmodule.tpl_namespace + var ns = mentity.intro.mclassdef.mmodule.html_namespace var section = new TplSection("intro") var title = new Template title.add "Introduction in " @@ -644,7 +644,7 @@ redef class DefinitionArticle # FIXME hideous hacks... if mentity isa MModule then article = mentity.tpl_article - article.subtitle = mentity.tpl_declaration + article.subtitle = mentity.html_declaration article.content = mentity.tpl_definition else if mentity isa MClass then article = make_mclass_article(v, page) @@ -655,7 +655,7 @@ redef class DefinitionArticle article = make_mpropdef_article(v, doc, page) else article = mentity.tpl_article - article.subtitle = mentity.tpl_declaration + article.subtitle = mentity.html_declaration if mentity isa MPropDef then article.source_link = v.tpl_showsource(mentity.location) end @@ -673,7 +673,7 @@ redef class DefinitionArticle private fun make_mclass_article(v: RenderHTMLPhase, page: MEntityPage): TplArticle do var article = mentity.tpl_article - article.subtitle = mentity.tpl_namespace + article.subtitle = mentity.html_namespace article.content = null return article end @@ -686,7 +686,7 @@ redef class DefinitionArticle end var title = new Template title.add "in " - title.add mclassdef.mmodule.tpl_namespace + title.add mclassdef.mmodule.html_namespace article.subtitle = title return article end @@ -700,8 +700,8 @@ redef class DefinitionArticle title.add mprop.tpl_icon title.add "" if mpropdef.is_intro then - title.add mprop.tpl_link - title.add mprop.intro.tpl_signature + title.add mprop.html_link + title.add mprop.intro.html_signature else var cls_url = mprop.intro.mclassdef.mclass.nitdoc_url var def_url = "{cls_url}#{mprop.nitdoc_id}" @@ -713,7 +713,7 @@ redef class DefinitionArticle article.title = title article.title_classes.add "signature" article.summary_title = "{mprop.html_name}" - article.subtitle = mpropdef.tpl_namespace + article.subtitle = mpropdef.html_namespace if mpropdef.mdoc_or_fallback != null then article.content = mpropdef.mdoc_or_fallback.tpl_comment end diff --git a/src/doc/html_templates/html_model.nit b/src/doc/html_templates/html_model.nit index 2908fad..a37dd2b 100644 --- a/src/doc/html_templates/html_model.nit +++ b/src/doc/html_templates/html_model.nit @@ -18,6 +18,7 @@ module html_model import doc_base import doc_down import html_components +import html::bootstrap import ordered_tree redef class Location @@ -56,9 +57,11 @@ redef class MEntity # * MPropdef: `foo(e)` var html_name: String is lazy do return name.html_escape - # A template link to the mentity `nitdoc_id` - fun tpl_anchor: TplLink do - var tpl = new TplLink("#{nitdoc_id}", html_name) + # Returns a Link to the mentity `html_url`. + # + # Example: `html_short_name + var html_link: Link is lazy do + var tpl = new Link(nitdoc_url, html_name) var mdoc = mdoc_or_fallback if mdoc != null then tpl.title = mdoc.short_comment @@ -66,9 +69,11 @@ redef class MEntity return tpl end - # A template link to the mentity `nitdoc_url` - fun tpl_link: TplLink do - var tpl = new TplLink(nitdoc_url, html_name) + # Returns a Link to the mentity `nitdoc_id`. + # + # Example: `html_short_name + fun html_link_to_anchor: Link do + var tpl = new Link("#{nitdoc_id}", html_name) var mdoc = mdoc_or_fallback if mdoc != null then tpl.title = mdoc.short_comment @@ -76,6 +81,39 @@ redef class MEntity return tpl end + # Returns the list of keyword used in `self` declaration. + fun html_modifiers: Array[String] is abstract + + # Returns the complete MEntity declaration decorated with HTML. + # + # * MProject: `project foo` + # * MGroup: `group foo` + # * MModule: `module foo` + # * MClass: `private abstract class Foo[E: Object]` + # * MClassDef: `redef class Foo[E]` + # * MProperty: `private fun foo(e: Object): Int` + # * MPropdef: `redef fun foo(e)` + fun html_declaration: Template do + var tpl = new Template + tpl.add "" + tpl.add html_modifiers.join(" ") + tpl.add " " + tpl.add html_link + tpl.add "" + return tpl + end + + # Returns `self` namespace decorated with HTML links. + # + # * MProject: `mproject` + # * MGroup: `mproject(::group)` + # * MModule: `mgroup::mmodule` + # * MClass: `mproject::mclass` + # * MClassDef: `mmodule::mclassdef` + # * MProperty: `mclass::mprop` + # * MPropdef: `mclassdef:mpropdef` + fun html_namespace: Template is abstract + # A template article that briefly describe the entity fun tpl_short_article: TplArticle do var tpl = tpl_article @@ -90,17 +128,11 @@ redef class MEntity fun tpl_article: TplArticle do var tpl = new TplArticle.with_title(nitdoc_id, tpl_title) tpl.title_classes.add "signature" - tpl.subtitle = tpl_namespace + tpl.subtitle = html_namespace tpl.summary_title = html_name return tpl end - # A template signature that contains modifiers and parameters - fun tpl_declaration: Template is abstract - - # A template namespace - fun tpl_namespace: Template is abstract - # A template definition of the mentity # include name, sysnopsys, comment and namespace fun tpl_definition: TplDefinition is abstract @@ -109,7 +141,7 @@ redef class MEntity fun tpl_list_item: TplListItem do var lnk = new Template lnk.add new TplLabel.with_classes(tpl_css_classes) - lnk.add tpl_link + lnk.add html_link var mdoc = mdoc_or_fallback if mdoc != null then lnk.add ": " @@ -124,7 +156,7 @@ redef class MEntity fun tpl_title: Template do var title = new Template title.add tpl_icon - title.add tpl_namespace + title.add html_namespace return title end @@ -140,7 +172,7 @@ redef class MConcern # Return a li element for `self` that can be displayed in a concern list private fun tpl_concern_item: TplListItem do var lnk = new Template - lnk.add tpl_anchor + lnk.add html_link_to_anchor var mdoc = mdoc_or_fallback if mdoc != null then lnk.add ": " @@ -153,16 +185,8 @@ end redef class MProject redef var nitdoc_id = name.to_cmangle is lazy redef fun nitdoc_url do return root.nitdoc_url - - redef fun tpl_declaration do - var tpl = new Template - tpl.add "project " - tpl.add tpl_link - tpl.add "" - return tpl - end - - redef fun tpl_namespace do return tpl_link + redef var html_modifiers = ["project"] + redef fun html_namespace do return html_link redef fun tpl_definition do var tpl = new TplDefinition @@ -185,25 +209,22 @@ redef class MGroup end redef fun nitdoc_url do return "group_{nitdoc_id}.html" + redef var html_modifiers = ["group"] - redef fun tpl_namespace do + # Depends if `self` is root or not. + # + # * If root `mproject`. + # * Else `mproject::self`. + redef fun html_namespace do var tpl = new Template - tpl.add mproject.tpl_namespace + tpl.add mproject.html_namespace if mproject.root != self then tpl.add "::" - tpl.add tpl_link + tpl.add html_link end return tpl end - redef fun tpl_declaration do - var tpl = new Template - tpl.add "group " - tpl.add tpl_link - tpl.add "" - return tpl - end - redef fun tpl_definition do var tpl = new TplDefinition var mdoc = mdoc_or_fallback @@ -227,22 +248,19 @@ redef class MModule end redef fun nitdoc_url do return "module_{nitdoc_id}.html" + redef var html_modifiers = ["module"] - redef fun tpl_declaration do - var tpl = new Template - tpl.add "module " - tpl.add tpl_namespace - tpl.add "" - return tpl - end - - redef fun tpl_namespace do + # Depends if `self` belongs to a MGroup. + # + # * If mgroup `mgroup::self`. + # * Else `self`. + redef fun html_namespace do var tpl = new Template if mgroup != null then - tpl.add mgroup.tpl_namespace + tpl.add mgroup.html_namespace tpl.add "::" end - tpl.add tpl_link + tpl.add html_link return tpl end @@ -279,67 +297,125 @@ redef class MClass return tpl.write_to_string end - redef fun tpl_declaration do return intro.tpl_declaration - redef fun tpl_definition do return intro.tpl_definition + redef fun html_modifiers do return intro.html_modifiers + redef fun html_declaration do return intro.html_declaration - redef fun tpl_namespace do + # Returns `mproject::self`. + redef fun html_namespace do var tpl = new Template - tpl.add intro_mmodule.mgroup.mproject.tpl_namespace + tpl.add intro_mmodule.mgroup.mproject.html_namespace tpl.add "::" - tpl.add tpl_link + tpl.add html_link tpl.add "" return tpl end + # Returns `intro.html_short_signature`. + fun html_short_signature: Template do return intro.html_short_signature + + # Returns `intro.html_signature`. + fun html_signature: Template do return intro.html_signature + + redef fun tpl_definition do return intro.tpl_definition + redef fun tpl_title do var title = new Template title.add tpl_icon - title.add tpl_link + title.add html_link return title end redef fun tpl_icon do return intro.tpl_icon - - fun tpl_signature: Template do - var tpl = new Template - if arity > 0 then - tpl.add "[" - var parameter_names = new Array[String] - for p in mparameters do - parameter_names.add(p.html_name) - end - tpl.add parameter_names.join(", ") - tpl.add "]" - end - return tpl - end - redef fun tpl_css_classes do return intro.tpl_css_classes end redef class MClassDef redef var nitdoc_id = "{mmodule.nitdoc_id}__{name.to_cmangle}" is lazy redef fun nitdoc_url do return "{mclass.nitdoc_url}#{nitdoc_id}" - redef fun mdoc_or_fallback do return mdoc or else mclass.mdoc_or_fallback - redef fun tpl_namespace do + # Depends if `self` is an intro or not. + # + # * If intro contains the visibility and kind. + # * If redef contains the `redef` keyword and kind. + redef fun html_modifiers do + var res = new Array[String] + if not is_intro then + res.add "redef" + else + if mclass.visibility != public_visibility then + res.add mclass.visibility.to_s + end + end + res.add mclass.kind.to_s + return res + end + + # Depends if `self` is an intro or not. + # + # For intro: `private abstract class Foo[E: Object]` + # For redef: `redef class Foo[E]` + # TODO change the implementation to correspond to the comment. + redef fun html_declaration do var tpl = new Template - tpl.add mmodule.tpl_namespace + tpl.add "" + tpl.add html_modifiers.join(" ") + tpl.add " " + tpl.add html_link + tpl.add html_signature + tpl.add "" + return tpl + end + + # Returns `mmodule::self` + redef fun html_namespace do + var tpl = new Template + tpl.add mmodule.html_namespace tpl.add "::" - tpl.add mclass.tpl_link + tpl.add mclass.html_link tpl.add "" return tpl end + # Returns the MClassDef generic signature without static bounds. + fun html_short_signature: Template do + var tpl = new Template + var mparameters = mclass.mparameters + if not mparameters.is_empty then + tpl.add "[" + for i in [0..mparameters.length[ do + tpl.add mparameters[i].html_name + if i < mparameters.length - 1 then tpl.add ", " + end + tpl.add "]" + end + return tpl + end + + # Returns the MClassDef generic signature with static bounds. + fun html_signature: Template do + var tpl = new Template + var mparameters = mclass.mparameters + if not mparameters.is_empty then + tpl.add "[" + for i in [0..mparameters.length[ do + tpl.add "{mparameters[i].html_name}: " + tpl.add bound_mtype.arguments[i].html_signature + if i < mparameters.length - 1 then tpl.add ", " + end + tpl.add "]" + end + return tpl + end + redef fun tpl_article do var tpl = new TplArticle(nitdoc_id) tpl.summary_title = "in {mmodule.html_name}" - tpl.title = tpl_declaration + tpl.title = html_declaration tpl.title_classes.add "signature" var title = new Template title.add "in " - title.add mmodule.tpl_namespace + title.add mmodule.html_namespace tpl.subtitle = title var mdoc = mdoc_or_fallback if mdoc != null then @@ -351,33 +427,10 @@ redef class MClassDef redef fun tpl_title do var title = new Template title.add tpl_icon - title.add tpl_link + title.add html_link return title end - redef fun tpl_declaration do - var tpl = new Template - tpl.add tpl_modifiers - tpl.add tpl_link - tpl.add tpl_signature - return tpl - end - - fun tpl_signature: Template do - var tpl = new Template - var mparameters = mclass.mparameters - if not mparameters.is_empty then - tpl.add "[" - for i in [0..mparameters.length[ do - tpl.add "{mparameters[i].html_name}: " - tpl.add bound_mtype.arguments[i].tpl_signature - if i < mparameters.length - 1 then tpl.add ", " - end - tpl.add "]" - end - return tpl - end - redef fun tpl_definition do var tpl = new TplClassDefinition var mdoc = mdoc_or_fallback @@ -408,21 +461,25 @@ end redef class MProperty redef var nitdoc_id = "{intro_mclassdef.mclass.nitdoc_id}__{name.to_cmangle}" is lazy redef fun nitdoc_url do return "property_{nitdoc_id}.html" - redef fun mdoc_or_fallback do return intro.mdoc + redef fun html_modifiers do return intro.html_modifiers + redef fun html_declaration do return intro.html_declaration - redef fun tpl_namespace do + # Returns `mclass::self`. + redef fun html_namespace do var tpl = new Template - tpl.add intro_mclassdef.mclass.tpl_namespace + tpl.add intro_mclassdef.mclass.html_namespace tpl.add "::" - tpl.add intro.tpl_link + tpl.add intro.html_link tpl.add "" return tpl end - redef fun tpl_declaration do return intro.tpl_declaration + # Returns `intro.html_short_signature`. + fun html_short_signature: Template do return intro.html_short_signature - fun tpl_signature: Template do return new Template + # Returns `intro.html_signature`. + fun html_signature: Template do return intro.html_signature redef fun tpl_title do return intro.tpl_title @@ -434,25 +491,63 @@ end redef class MPropDef redef var nitdoc_id = "{mclassdef.nitdoc_id}__{name.to_cmangle}" is lazy redef fun nitdoc_url do return "{mproperty.nitdoc_url}#{nitdoc_id}" - redef fun mdoc_or_fallback do return mdoc or else mproperty.mdoc_or_fallback - redef fun tpl_namespace do + # Depends if `self` is an intro or not. + # + # * If intro contains the visibility and kind. + # * If redef contains the `redef` keyword and kind. + redef fun html_modifiers do + var res = new Array[String] + if not is_intro then + res.add "redef" + else + if mproperty.visibility != public_visibility then + res.add mproperty.visibility.to_s + end + end + return res + end + + # Depends if `self` is an intro or not. + # + # For intro: `private fun foo(e: Object): Bar is abstract` + # For redef: `redef fun foo(e) is cached` + # TODO change the implementation to correspond to the comment. + redef fun html_declaration do var tpl = new Template - tpl.add mclassdef.tpl_namespace + tpl.add "" + tpl.add html_modifiers.join(" ") + tpl.add " " + tpl.add html_link + tpl.add html_signature + tpl.add "" + return tpl + end + + # Returns `mclassdef::self` + redef fun html_namespace do + var tpl = new Template + tpl.add mclassdef.html_namespace tpl.add "::" - tpl.add tpl_link + tpl.add html_link return tpl end + # Returns the MPropdDef signature without static types. + fun html_short_signature: Template is abstract + + # Returns the MPropDef signature with static types. + fun html_signature: Template is abstract + redef fun tpl_article do var tpl = new TplArticle(nitdoc_id) tpl.summary_title = "in {mclassdef.html_name}" var title = new Template title.add "in " - title.add mclassdef.tpl_link + title.add mclassdef.html_link tpl.title = title - tpl.subtitle = tpl_declaration + tpl.subtitle = html_declaration var mdoc = mdoc_or_fallback if mdoc != null then tpl.content = mdoc.tpl_comment @@ -469,14 +564,6 @@ redef class MPropDef return tpl end - redef fun tpl_declaration do - var tpl = new Template - tpl.add tpl_modifiers - tpl.add tpl_link - tpl.add tpl_signature - return tpl - end - redef fun tpl_css_classes do var set = new HashSet[String] if is_intro then set.add "intro" @@ -494,13 +581,13 @@ redef class MPropDef return tpl end - fun tpl_signature: Template do return new Template - redef fun tpl_list_item do var lnk = new Template lnk.add new TplLabel.with_classes(tpl_css_classes.to_a) - var anchor = tpl_link - anchor.href = "{mclassdef.mclass.nitdoc_url}#{mproperty.nitdoc_id}" + var atext = html_link.text + var ahref = "{mclassdef.mclass.nitdoc_url}#{mproperty.nitdoc_id}" + var atitle = html_link.title + var anchor = new Link.with_title(ahref, atext, atitle) lnk.add anchor var mdoc = mdoc_or_fallback if mdoc != null then @@ -513,10 +600,12 @@ redef class MPropDef fun tpl_inheritance_item: TplListItem do var lnk = new Template lnk.add new TplLabel.with_classes(tpl_css_classes.to_a) - lnk.add mclassdef.mmodule.tpl_namespace + lnk.add mclassdef.mmodule.html_namespace lnk.add "::" - var anchor = mclassdef.tpl_link - anchor.href = "{mclassdef.mclass.nitdoc_url}#{mproperty.nitdoc_id}" + var atext = mclassdef.html_link.text + var ahref = "{mclassdef.mclass.nitdoc_url}#{mproperty.nitdoc_id}" + var atitle = mclassdef.html_link.title + var anchor = new Link.with_title(ahref, atext, atitle) lnk.add anchor var mdoc = mdoc_or_fallback if mdoc != null then @@ -530,78 +619,122 @@ redef class MPropDef end redef class MAttributeDef - redef fun tpl_signature do + + redef fun html_modifiers do + var res = super + res.add "var" + return res + end + + redef fun html_short_signature do return new Template + + redef fun html_signature do var tpl = new Template if static_mtype != null then tpl.add ": " - tpl.add static_mtype.tpl_signature + tpl.add static_mtype.html_signature end return tpl end end -redef class MMethod - redef fun tpl_signature do - var tpl = new Template - var params = new Array[String] - for param in intro.msignature.mparameters do - params.add param.name.html_escape +redef class MMethodDef + + # FIXME annotation should be handled in their own way + redef fun html_modifiers do + var res = super + if is_abstract then + res.add "abstract" + else if is_intern then + res.add "intern" end - if not params.is_empty then - tpl.add "(" - tpl.add params.join(", ") - tpl.add ")" + if mproperty.is_init then + res.add "init" + else + res.add "fun" end - return tpl + return res end -end -redef class MMethodDef - redef fun tpl_signature do return msignature.tpl_signature + redef fun html_short_signature do return msignature.html_short_signature + redef fun html_signature do return msignature.html_signature end redef class MVirtualTypeProp - redef fun tpl_link do return mvirtualtype.tpl_link - redef fun tpl_signature do return tpl_link + redef fun html_link do return mvirtualtype.html_link end redef class MVirtualTypeDef - redef fun tpl_signature do + + redef fun html_modifiers do + var res = super + res.add "type" + return res + end + + redef fun html_short_signature do return new Template + + redef fun html_signature do var tpl = new Template if bound == null then return tpl tpl.add ": " - tpl.add bound.tpl_signature + tpl.add bound.html_signature return tpl end end redef class MType - fun tpl_signature: Template is abstract + # Returns the signature of this type whithout bounds. + fun html_short_signature: Template is abstract + + # Returns the signature of this type. + fun html_signature: Template is abstract end redef class MClassType - redef fun tpl_link do return mclass.tpl_link - redef fun tpl_signature do return tpl_link + redef fun html_link do return mclass.html_link + redef fun html_short_signature do return html_link + redef fun html_signature do return html_link end redef class MNullableType - redef fun tpl_signature do + + redef fun html_short_signature do + var tpl = new Template + tpl.add "nullable " + tpl.add mtype.html_short_signature + return tpl + end + + redef fun html_signature do var tpl = new Template tpl.add "nullable " - tpl.add mtype.tpl_signature + tpl.add mtype.html_signature return tpl end end redef class MGenericType - redef fun tpl_signature do + redef fun html_short_signature do + var lnk = html_link var tpl = new Template - var lnk = tpl_link - lnk.text = mclass.name.html_escape - tpl.add lnk + tpl.add new Link.with_title(lnk.href, mclass.name.html_escape, lnk.title) tpl.add "[" for i in [0..arguments.length[ do - tpl.add arguments[i].tpl_signature + tpl.add arguments[i].html_short_signature + if i < arguments.length - 1 then tpl.add ", " + end + tpl.add "]" + return tpl + end + + redef fun html_signature do + var lnk = html_link + var tpl = new Template + tpl.add new Link.with_title(lnk.href, mclass.name.html_escape, lnk.title) + tpl.add "[" + for i in [0..arguments.length[ do + tpl.add arguments[i].html_signature if i < arguments.length - 1 then tpl.add ", " end tpl.add "]" @@ -610,41 +743,67 @@ redef class MGenericType end redef class MParameterType - redef fun tpl_link do - return new TplLink.with_title("{mclass.nitdoc_url}#FT_{name.to_cmangle}", name, "formal type") + redef fun html_link do + return new Link.with_title("{mclass.nitdoc_url}#FT_{name.to_cmangle}", name, "formal type") end - redef fun tpl_signature do return tpl_link + + redef fun html_short_signature do return html_link + redef fun html_signature do return html_link end redef class MVirtualType - redef fun tpl_link do return mproperty.intro.tpl_link - redef fun tpl_signature do return tpl_link + redef fun html_link do return mproperty.intro.html_link + redef fun html_signature do return html_link end redef class MSignature - redef fun tpl_signature do + + redef fun html_short_signature do var tpl = new Template if not mparameters.is_empty then tpl.add "(" for i in [0..mparameters.length[ do - tpl.add mparameters[i].tpl_signature + tpl.add mparameters[i].html_short_signature + if i < mparameters.length - 1 then tpl.add ", " + end + tpl.add ")" + end + return tpl + end + + redef fun html_signature do + var tpl = new Template + if not mparameters.is_empty then + tpl.add "(" + for i in [0..mparameters.length[ do + tpl.add mparameters[i].html_signature if i < mparameters.length - 1 then tpl.add ", " end tpl.add ")" end if return_mtype != null then tpl.add ": " - tpl.add return_mtype.tpl_signature + tpl.add return_mtype.html_signature end return tpl end end redef class MParameter - fun tpl_signature: Template do + + # Returns `self` name and ellipsys if any. + fun html_short_signature: Template do + var tpl = new Template + tpl.add name + if is_vararg then tpl.add "..." + return tpl + end + + # Returns `self` name with it's static type and ellipsys if any. + fun html_signature: Template do var tpl = new Template tpl.add "{name}: " - tpl.add mtype.tpl_signature + tpl.add mtype.html_signature if is_vararg then tpl.add "..." return tpl end @@ -692,12 +851,12 @@ end # Additions to `model_ext`. redef class MRawType - redef fun tpl_signature do + redef fun html_signature do var tpl = new Template for part in parts do if part.target != null then - tpl.add part.target.as(not null).tpl_link + tpl.add part.target.as(not null).html_link else tpl.add part.text.html_escape end @@ -708,15 +867,15 @@ end redef class MInnerClass redef fun nitdoc_url do return inner.nitdoc_url - redef fun tpl_signature do return inner.tpl_signature + redef fun html_signature do return inner.html_signature end redef class MInnerClassDef redef fun nitdoc_url do return inner.nitdoc_url - redef fun tpl_anchor do return inner.tpl_anchor - redef fun tpl_link do return inner.tpl_link - redef fun tpl_signature do return inner.tpl_signature + redef fun html_link_to_anchor do return inner.html_link_to_anchor + redef fun html_link do return inner.html_link + redef fun html_signature do return inner.html_signature redef fun tpl_definition do var tpl = new TplClassDefinition