--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Generate files used by the Vim plugin to autocomplete with doc
+#
+# There is 3 files generated, each with a different target: modules, classes,
+# and properties. Each line describe a different entity, with 4 values:
+#
+# 1. Short name to use in autocompletion
+# 2. Full signature
+# 3. Doc synopsis
+# 4. Full doc with extra
+#
+# The priority with those files is for them to be analyzed efficiently, for
+# this reason, the data is prepared in advant and some information may be
+# duplicated.
+module vim_autocomplete
+
+import modelbuilder
+import phase
+import modelize::modelize_class
+
+redef class ToolContext
+ # Phase generating the files for the Vim plugin
+ var autocomplete_phase: Phase = new AutocompletePhase(self, [modelize_class_phase])
+
+ # Shall we generate the files for the Vim plugin?
+ var opt_vim_autocomplete = new OptionBool(
+ "Generate metadata files used by the Vim plugin for autocompletion", "--vim-autocomplete")
+
+ init
+ do
+ super
+ option_context.add_option opt_vim_autocomplete
+ end
+end
+
+redef class MEntity
+ private fun field_separator: String do return "#====#"
+ private fun line_separator: String do return "#nnnn#"
+
+ private fun write_to_stream(stream: OStream)
+ do
+ # 1. Short name for autocompletion
+ stream.write name
+ stream.write field_separator
+
+ # 2. Full signature
+ stream.write name
+ write_signature_to_stream(stream)
+ stream.write field_separator
+
+ # 3. Doc synopsis
+ var mdoc = mdoc
+ if mdoc != null then
+ stream.write mdoc.content.first
+ end
+
+ # 4. Full doc with extra
+ stream.write field_separator
+ if mdoc != null then
+ stream.write "# "
+ stream.write full_name
+ write_signature_to_stream(stream)
+ for i in 2.times do stream.write line_separator
+ stream.write mdoc.content.join(line_separator)
+ end
+
+ stream.write "\n"
+ end
+
+ private fun write_signature_to_stream(stream: OStream) do end
+end
+
+redef class MMethodDef
+ redef fun write_signature_to_stream(stream)
+ do
+ var msignature = msignature
+ if msignature != null then
+ stream.write msignature.to_s
+ end
+ end
+end
+
+redef class MAttributeDef
+ redef fun write_signature_to_stream(stream)
+ do
+ var static_mtype = static_mtype
+ if static_mtype != null then
+ stream.write stream.to_s
+ end
+ end
+end
+
+private class AutocompletePhase
+ super Phase
+
+ redef fun process_mainmodule(mainmodule, given_mmodules)
+ do
+ if not toolcontext.opt_vim_autocomplete.value then return
+
+ var compile_dir = "NIT_VIM_DIR".environ
+ if compile_dir.is_empty then compile_dir = "HOME".environ / ".vim/nit"
+ compile_dir.mkdir
+ var modules_stream = new OFStream.open(compile_dir / "modules.txt")
+ var classes_stream = new OFStream.open(compile_dir / "classes.txt")
+ var properties_stream = new OFStream.open(compile_dir / "properties.txt")
+
+ # Got all known modules
+ var model = mainmodule.model
+ for mmodule in model.mmodules do
+ mmodule.write_to_stream modules_stream
+ end
+
+ # TODO list other modules from the Nit lib
+ # TODO list submodules
+
+ # Get all known classes
+ for mclass in model.mclasses do
+ if not mainmodule.is_visible(mclass.intro_mmodule, public_visibility) then continue
+
+ mclass.intro.write_to_stream classes_stream
+ end
+
+ # Get all known properties
+ for mproperty in model.mproperties do
+ var intro_mmodule = mproperty.intro_mclassdef.mmodule
+ if not mainmodule.is_visible(intro_mmodule, public_visibility) then continue
+
+ mproperty.intro.write_to_stream properties_stream
+ end
+
+ # Close streams
+ for stream in [modules_stream, classes_stream, properties_stream] do
+ stream.close
+
+ var error = stream.last_error
+ if error != null then
+ toolcontext.error(null, "Failed to write Vim autocomplete file: {error}")
+ end
+ end
+ end
+end