cmd/commands_http: clean Int options handling
[nit.git] / src / doc / api / api_docdown.nit
index 561f0af..fdbb8db 100644 (file)
 # Nitdoc specific Markdown format handling for Nitweb
 module api_docdown
 
-import api_graph
-intrude import doc_down
-intrude import markdown::wikilinks
-import doc_commands
-import model::model_index
+import api_model
+import commands::commands_docdown
 
 redef class NitwebConfig
        # Specific Markdown processor to use within Nitweb
        var md_processor: MarkdownProcessor is lazy do
-               var proc = new MarkdownProcessor
-               proc.decorator = new NitwebDecorator(view, modelbuilder)
+               var parser = new CommandParser(model, mainmodule, modelbuilder, catalog)
+               var proc = new CmdMarkdownProcessor(parser)
+               proc.decorator = new CmdDecorator(model)
                return proc
        end
 end
@@ -45,295 +43,3 @@ class APIDocdown
                res.html config.md_processor.process(req.body)
        end
 end
-
-# Specific Markdown decorator for Nitweb
-#
-# We reuse all the implementation of the NitdocDecorator and add the wikilinks handling.
-class NitwebDecorator
-       super NitdocDecorator
-
-       # View used by wikilink commands to find model entities
-       var view: ModelView
-
-       # Modelbuilder used to access code
-       var modelbuilder: ModelBuilder
-
-       redef fun add_span_code(v, buffer, from, to) do
-               var text = new FlatBuffer
-               buffer.read(text, from, to)
-               var name = text.write_to_string
-               name = name.replace("nullable ", "")
-               var mentity = try_find_mentity(view, name)
-               if mentity == null then
-                       super
-               else
-                       v.add "<code>"
-                       v.write_mentity_link(mentity, text.write_to_string)
-                       v.add "</code>"
-               end
-       end
-
-       private fun try_find_mentity(view: ModelView, text: String): nullable MEntity do
-               var mentity = view.mentity_by_full_name(text)
-               if mentity != null then return mentity
-
-               var mentities = view.mentities_by_name(text)
-               if mentities.is_empty then
-                       return null
-               else if mentities.length > 1 then
-                       # TODO smart resolve conflicts
-               end
-               return mentities.first
-       end
-
-       redef fun add_wikilink(v, token) do
-               v.render_wikilink(token, view)
-       end
-end
-
-# Same as `InlineDecorator` but with wikilink commands handling
-class NitwebInlineDecorator
-       super InlineDecorator
-
-       # View used by wikilink commands to find model entities
-       var view: ModelView
-
-       # Modelbuilder used to access code
-       var modelbuilder: ModelBuilder
-
-       redef fun add_wikilink(v, token) do
-               v.render_wikilink(token, view)
-       end
-end
-
-redef class MarkdownProcessor
-
-       # Parser used to process doc commands
-       var parser = new DocCommandParser
-
-       # Render a wikilink
-       fun render_wikilink(token: TokenWikiLink, model: ModelView) do
-               var link = token.link
-               if link == null then return
-               var name = token.name
-               if name != null then link = "{name} | {link}"
-               var cmd = parser.parse(link.write_to_string)
-               if cmd == null then
-                       var full_name = if token.link != null then token.link.as(not null).write_to_string.trim else null
-                       if full_name == null or full_name.is_empty then
-                               write_error("empty wikilink")
-                               return
-                       end
-                       var mentity = find_mentity(model, full_name)
-                       if mentity == null then return
-                       name = if token.name != null then token.name.as(not null).to_s else null
-                       write_mentity_link(mentity, name)
-                       return
-               else
-                       for message in parser.errors do
-                               if message.level == 1 then
-                                       write_error(message.message)
-                               else if message.level > 1 then
-                                       write_warning(message.message)
-                               end
-                       end
-               end
-               cmd.render(self, token, model)
-       end
-
-       # Find the MEntity that matches `name`.
-       #
-       # Write an error if the entity is not found
-       fun find_mentity(model: ModelView, name: nullable String): nullable MEntity do
-               if name == null then
-                       write_error("no MEntity found")
-                       return null
-               end
-               # Lookup by full name
-               var mentity = model.mentity_by_full_name(name)
-               if mentity != null then return mentity
-
-               var mentities = model.mentities_by_name(name)
-               if mentities.is_empty then
-                       var suggest = model.find(name, 3)
-                       var msg = new Buffer
-                       msg.append "no MEntity found for name `{name}`"
-                       if suggest.not_empty then
-                               msg.append " (suggestions: "
-                               var i = 0
-                               for s in suggest do
-                                       msg.append "`{s.full_name}`"
-                                       if i < suggest.length - 1 then msg.append ", "
-                                       i += 1
-                               end
-                               msg.append ")"
-                       end
-                       write_error(msg.write_to_string)
-                       return null
-               else if mentities.length > 1 then
-                       var msg = new Buffer
-                       msg.append "conflicts for name `{name}`"
-                       msg.append " (conflicts: "
-                       var i = 0
-                       for s in mentities do
-                               msg.append "`{s.full_name}`"
-                               if i < mentities.length - 1 then msg.append ", "
-                               i += 1
-                       end
-                       msg.append ")"
-                       write_warning(msg.write_to_string)
-               end
-               return mentities.first
-       end
-
-       # Write a warning in the output
-       fun write_warning(text: String) do
-               emit_text "<p class='text-warning'>Warning: {text}</p>"
-       end
-
-       # Write an error in the output
-       fun write_error(text: String) do
-               emit_text "<p class='text-danger'>Error: {text}</p>"
-       end
-
-       # Write a link to a mentity in the output
-       fun write_mentity_link(mentity: MEntity, text: nullable String) do
-               var link = mentity.web_url
-               var name = text or else mentity.name
-               var mdoc = mentity.mdoc_or_fallback
-               var comment = null
-               if mdoc != null then comment = mdoc.synopsis
-               decorator.add_link(self, link, name, comment)
-       end
-
-       # Write a mentity list in the output
-       fun write_mentity_list(mentities: Collection[MEntity]) do
-               add "<ul>"
-               for mentity in mentities do
-                       var mdoc = mentity.mdoc_or_fallback
-                       add "<li>"
-                       write_mentity_link(mentity)
-                       if mdoc != null then
-                               add " - "
-                               emit_text mdoc.synopsis
-                       end
-                       add "</li>"
-               end
-               add "</ul>"
-       end
-end
-
-redef class DocCommand
-
-       # Emit the HTML related to the execution of this doc command
-       fun render(v: MarkdownProcessor, token: TokenWikiLink, model: ModelView) do
-               v.write_error("not yet implemented command `{token.link or else "null"}`")
-       end
-end
-
-redef class CommentCommand
-       redef fun render(v, token, model) do
-               var name = arg
-               var mentity = v.find_mentity(model, name)
-               if mentity == null then return
-               var mdoc = mentity.mdoc_or_fallback
-               if mdoc == null then
-                       v.write_warning("no MDoc for mentity `{name}`")
-                       return
-               end
-               v.add "<h3>"
-               if not opts.has_key("no-link") then
-                       v.write_mentity_link(mentity)
-               end
-               if not opts.has_key("no-link") and not opts.has_key("no-synopsis") then
-                       v.add " - "
-               end
-               if not opts.has_key("no-synopsis") then
-                       v.emit_text mdoc.html_synopsis.write_to_string
-               end
-               v.add "</h3>"
-               if not opts.has_key("no-comment") then
-                       v.add v.process(mdoc.comment).write_to_string
-               end
-       end
-end
-
-redef class ListCommand
-       redef fun render(v, token, model) do
-               var name = arg
-               var mentity = v.find_mentity(model, name)
-               if mentity == null then return
-               if mentity isa MPackage then
-                       v.write_mentity_list(mentity.mgroups)
-               else if mentity isa MGroup then
-                       var res = new Array[MEntity]
-                       res.add_all mentity.in_nesting.smallers
-                       res.add_all mentity.mmodules
-                       v.write_mentity_list(res)
-               else if mentity isa MModule then
-                       v.write_mentity_list(mentity.mclassdefs)
-               else if mentity isa MClass then
-                       v.write_mentity_list(mentity.collect_intro_mproperties(model))
-               else if mentity isa MClassDef then
-                       v.write_mentity_list(mentity.mpropdefs)
-               else if mentity isa MProperty then
-                       v.write_mentity_list(mentity.mpropdefs)
-               else
-                       v.write_error("no list found for name `{name}`")
-               end
-       end
-end
-
-redef class CodeCommand
-       redef fun render(v, token, model) do
-               var name = arg
-               var mentity = v.find_mentity(model, name)
-               if mentity == null then return
-               if mentity isa MClass then mentity = mentity.intro
-               if mentity isa MProperty then mentity = mentity.intro
-               var source = render_source(mentity, v.decorator.as(NitwebDecorator).modelbuilder)
-               if source == null then
-                       v.write_error("no source for MEntity `{name}`")
-                       return
-               end
-               v.add "<pre>"
-               v.add source
-               v.add "</pre>"
-       end
-
-       # Highlight `mentity` source code.
-       private fun render_source(mentity: MEntity, modelbuilder: ModelBuilder): nullable HTMLTag do
-               var node = modelbuilder.mentity2node(mentity)
-               if node == null then return null
-               var hl = new HtmlightVisitor
-               hl.highlight_node node
-               return hl.html
-       end
-end
-
-redef class GraphCommand
-       redef fun render(v, token, model) do
-               var name = arg
-               var mentity = v.find_mentity(model, name)
-               if mentity == null then return
-               var g = new InheritanceGraph(mentity, model)
-               var pdepth = if opts.has_key("pdepth") and opts["pdepth"].is_int then
-                       opts["pdepth"].to_i else 3
-               var cdepth = if opts.has_key("cdepth") and opts["cdepth"].is_int then
-                       opts["cdepth"].to_i else 3
-               v.add g.draw(pdepth, cdepth).to_svg
-       end
-end
-
-redef class Text
-       # Read `self` between `nstart` and `nend` (excluded) and writte chars to `out`.
-       private fun read(out: FlatBuffer, nstart, nend: Int): Int do
-               var pos = nstart
-               while pos < length and pos < nend do
-                       out.add self[pos]
-                       pos += 1
-               end
-               if pos == length then return -1
-               return pos
-       end
-end