bcc904140f98b0f8ecc9befad784a42e1cccc7f4
[nit.git] / src / doc / vim_autocomplete.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 # Generate files used by the Vim plugin to autocomplete with doc
16 #
17 # There is 3 files generated, each with a different target: modules, classes,
18 # and properties. Each line describe a different entity, with 4 values:
19 #
20 # 1. Short name to use in autocompletion
21 # 2. Full signature
22 # 3. Doc synopsis
23 # 4. Full doc with extra
24 #
25 # The priority with those files is for them to be analyzed efficiently, for
26 # this reason, the data is prepared in advant and some information may be
27 # duplicated.
28 module vim_autocomplete
29
30 import modelbuilder
31 import phase
32 import modelize::modelize_class
33
34 redef class ToolContext
35 # Phase generating the files for the Vim plugin
36 var autocomplete_phase: Phase = new AutocompletePhase(self, [modelize_class_phase])
37
38 # Shall we generate the files for the Vim plugin?
39 var opt_vim_autocomplete = new OptionBool(
40 "Generate metadata files used by the Vim plugin for autocompletion", "--vim-autocomplete")
41
42 init
43 do
44 super
45 option_context.add_option opt_vim_autocomplete
46 end
47 end
48
49 redef class MEntity
50 private fun field_separator: String do return "#====#"
51 private fun line_separator: String do return "#nnnn#"
52
53 private fun write_to_stream(stream: OStream)
54 do
55 # 1. Short name for autocompletion
56 stream.write name
57 stream.write field_separator
58
59 # 2. Full signature
60 stream.write name
61 write_signature_to_stream(stream)
62 stream.write field_separator
63
64 # 3. Doc synopsis
65 var mdoc = mdoc
66 if mdoc != null then
67 stream.write mdoc.content.first
68 end
69
70 # 4. Full doc with extra
71 stream.write field_separator
72 if mdoc != null then
73 stream.write "# "
74 stream.write full_name
75 write_signature_to_stream(stream)
76 for i in 2.times do stream.write line_separator
77 stream.write mdoc.content.join(line_separator)
78 end
79
80 stream.write "\n"
81 end
82
83 private fun write_signature_to_stream(stream: OStream) do end
84 end
85
86 redef class MMethodDef
87 redef fun write_signature_to_stream(stream)
88 do
89 var msignature = msignature
90 if msignature != null then
91 stream.write msignature.to_s
92 end
93 end
94 end
95
96 redef class MAttributeDef
97 redef fun write_signature_to_stream(stream)
98 do
99 var static_mtype = static_mtype
100 if static_mtype != null then
101 stream.write stream.to_s
102 end
103 end
104 end
105
106 private class AutocompletePhase
107 super Phase
108
109 redef fun process_mainmodule(mainmodule, given_mmodules)
110 do
111 if not toolcontext.opt_vim_autocomplete.value then return
112
113 var compile_dir = "NIT_VIM_DIR".environ
114 if compile_dir.is_empty then compile_dir = "HOME".environ / ".vim/nit"
115 compile_dir.mkdir
116 var modules_stream = new OFStream.open(compile_dir / "modules.txt")
117 var classes_stream = new OFStream.open(compile_dir / "classes.txt")
118 var properties_stream = new OFStream.open(compile_dir / "properties.txt")
119
120 # Got all known modules
121 var model = mainmodule.model
122 for mmodule in model.mmodules do
123 mmodule.write_to_stream modules_stream
124 end
125
126 # TODO list other modules from the Nit lib
127 # TODO list submodules
128
129 # Get all known classes
130 for mclass in model.mclasses do
131 if not mainmodule.is_visible(mclass.intro_mmodule, public_visibility) then continue
132
133 mclass.intro.write_to_stream classes_stream
134 end
135
136 # Get all known properties
137 for mproperty in model.mproperties do
138 var intro_mmodule = mproperty.intro_mclassdef.mmodule
139 if not mainmodule.is_visible(intro_mmodule, public_visibility) then continue
140
141 # Skip properties beginning with @ or _
142 var first_letter = mproperty.name.chars.first
143 if first_letter == '@' or first_letter == '_' then continue
144
145 mproperty.intro.write_to_stream properties_stream
146 end
147
148 # Close streams
149 for stream in [modules_stream, classes_stream, properties_stream] do
150 stream.close
151
152 var error = stream.last_error
153 if error != null then
154 toolcontext.error(null, "Failed to write Vim autocomplete file: {error}")
155 end
156 end
157 end
158 end