fa95f6c96798cac1d7121d3cd90c278264e0da30
[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): HLCode
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 var hlcode = new HLCode(hl, content, source)
49
50 # Check syntax error
51 var eof = tree.n_eof
52 if eof isa AError then
53 mb.error(eof, eof.message)
54 hl.hightlight_source(source)
55 return hlcode
56 end
57 var amodule = tree.n_base.as(not null)
58
59 # Load the AST as a module in the model
60 # Then process it
61 mb.load_rt_module(null, amodule, "")
62 mb.run_phases
63
64 # Highlight the processed module
65 hl.enter_visit(amodule)
66 return hlcode
67 end
68
69 # A standalone highlighted piece of code
70 class HLCode
71 # The highlighter used
72 var hl: HighlightVisitor
73
74 # The raw code source
75 var content: String
76
77 # The pseudo source-file
78 var source: SourceFile
79 end
80
81 # Nitcorn service to hightlight code
82 #
83 # It's a single stand-alone page that has to form to itself.
84 class HighlightAction
85 super Action
86
87 redef fun answer(http_request, turi)
88 do
89 var hl = new HighlightVisitor
90 var page = new Template
91 var code = http_request.post_args.get_or_null("code")
92
93 page.add """
94 <!doctype html><html><head>{{{hl.head_content}}}
95 <style>
96 {{{hl.css_content}}}
97 textarea {width:100%;}
98 </style></head><body>
99 """
100 # Add the form+textarea
101 page.add """
102 <form action="#light" method=post><textarea id=code name=code rows=10>{{{code or else ""}}}</textarea><br><input type=submit></form>
103 """
104
105 if code != null then
106 # There is code? Process it
107 var hlcode = hightlightcode(hl, code)
108
109 # Inject highlight
110 page.add "<pre id=light><code id=lightcode>"
111 page.add hl.html.write_to_string
112 page.add "</code></pre><hr>"
113 page.add "<ul>"
114
115 # List messages
116 for m in hlcode.source.messages do
117 page.add "<li>{m.location.as(not null)}: {m.text}</li>"
118 end
119 page.add "</ul>"
120 end
121
122 page.add hl.foot_content
123 page.add """
124 </body></html>
125 """
126
127 var response = new HttpResponse(200)
128 response.header["Content-Type"] = "text/html"
129 response.body = page.write_to_string
130 return response
131 end
132 end
133
134 var host = "localhost:8080"
135 if args.length > 0 then host = args.first
136
137 var vh = new VirtualHost(host)
138 vh.routes.add new Route("/", new HighlightAction)
139 var factory = new HttpFactory.and_libevent
140 factory.config.virtual_hosts.add vh
141 factory.run