a9cead1fe409847ef6b4272b46780bae93d7ca75
[nit.git] / src / examples / nitlight_as_a_service.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 # This is an example of a client of the frontend without command-line processing.
16 #
17 # It offers a simple nitcorn web server that offers a textarea and nitpick and nitlignt it.
18 module nitlight_as_a_service
19
20 import frontend
21 import highlight
22 import nitcorn
23 import nitcorn::log
24 import template
25
26 # Fully process a content as a nit source file.
27 fun hightlightcode(hl: HighlightVisitor, content: String): SourceFile
28 do
29 # Prepare a stand-alone tool context
30 var tc = new ToolContext
31 tc.nit_dir = tc.locate_nit_dir # still use the common lib to have core
32 tc.keep_going = true # no exit, obviously
33 tc.opt_warn.value = -1 # no output, obviously
34
35 # Prepare an stand-alone model and model builder.
36 # Unfortunately, models are enclosing and append-only.
37 # There is no way (yet?) to have a shared module `core` with
38 # isolated and throwable user modules.
39 var model = new Model
40 var mb = new ModelBuilder(model, tc)
41
42 # Parse the code
43 var source = new SourceFile.from_string("", content)
44 var lexer = new Lexer(source)
45 var parser = new Parser(lexer)
46 var tree = parser.parse
47
48 # Check syntax error
49 var eof = tree.n_eof
50 if eof isa AError then
51 mb.error(eof, eof.message)
52 hl.hightlight_source(source)
53 return source
54 end
55 var amodule = tree.n_base.as(not null)
56
57 # Load the AST as a module in the model
58 # Then process it
59 mb.load_rt_module(null, amodule, "")
60 mb.run_phases
61
62 # Highlight the processed module
63 hl.enter_visit(amodule)
64 return source
65 end
66
67 # Nitcorn service to hightlight code
68 #
69 # It's a single stand-alone page that has to form to itself.
70 class HighlightAction
71 super Action
72
73 redef fun answer(http_request, turi)
74 do
75 var hl = new HighlightVisitor
76 var page = new Template
77 var code = http_request.post_args.get_or_null("code")
78
79 page.add """
80 <!doctype html><html><head>{{{hl.head_content}}}
81 <style>
82 {{{hl.css_content}}}
83 textarea {width:100%;}
84 </style></head><body>
85 """
86 # Add the form+textarea
87 page.add """
88 <form action="#light" method=post><textarea id=code name=code rows=10>{{{code or else ""}}}</textarea><br><input type=submit></form>
89 """
90
91 if code != null then
92 # There is code? Process it
93 var source = hightlightcode(hl, code)
94
95 # Inject highlight
96 page.add "<pre id=light><code id=lightcode>"
97 page.add hl.html.write_to_string
98 page.add "</code></pre><hr>"
99 page.add "<ul>"
100
101 # List messages
102 for m in source.messages do
103 page.add "<li>{m.location.as(not null)}: {m.text}</li>"
104 end
105 page.add "</ul>"
106 end
107
108 page.add hl.foot_content
109 page.add """
110 </body></html>
111 """
112
113 var response = new HttpResponse(200)
114 response.header["Content-Type"] = "text/html"
115 response.body = page.write_to_string
116 return response
117 end
118 end
119
120 var host = "localhost:8080"
121 if args.length > 0 then host = args.first
122
123 var vh = new VirtualHost(host)
124 vh.routes.add new Route("/", new HighlightAction)
125 var factory = new HttpFactory.and_libevent
126 factory.config.virtual_hosts.add vh
127 factory.run