summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.ycm_extra_conf.py126
-rw-r--r--Documentation/VimConfiguration.md12
2 files changed, 138 insertions, 0 deletions
diff --git a/.ycm_extra_conf.py b/.ycm_extra_conf.py
new file mode 100644
index 0000000000..3b1277a94f
--- /dev/null
+++ b/.ycm_extra_conf.py
@@ -0,0 +1,126 @@
+# Based on the example .ycm_extra_conf.py from YouCompleteMe, adapted
+# for SerenityOS.
+#
+# This file is NOT licensed under the GPLv3, which is the license for the rest
+# of YouCompleteMe.
+#
+# Here's the license text for this file:
+#
+# This is free and unencumbered software released into the public domain.
+#
+# Anyone is free to copy, modify, publish, use, compile, sell, or
+# distribute this software, either in source code form or as a compiled
+# binary, for any purpose, commercial or non-commercial, and by any
+# means.
+#
+# In jurisdictions that recognize copyright laws, the author or authors
+# of this software dedicate any and all copyright interest in the
+# software to the public domain. We make this dedication for the benefit
+# of the public at large and to the detriment of our heirs and
+# successors. We intend this dedication to be an overt act of
+# relinquishment in perpetuity of all present and future rights to this
+# software under copyright law.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+# For more information, please refer to <http://unlicense.org/>
+
+import os
+import subprocess
+import ycm_core
+
+DIR_OF_THIS_SCRIPT = os.path.abspath(os.path.dirname(__file__))
+SOURCE_EXTENSIONS = ['.cpp', '.c']
+
+gcc_path = None
+for serenity_arch in ['x86_64', 'i686', 'aarch64']:
+ candidate_gcc_path = os.path.join(
+ DIR_OF_THIS_SCRIPT, 'Toolchain',
+ 'Local', serenity_arch, 'bin', f'{serenity_arch}-pc-serenity-gcc'
+ )
+ if os.path.isfile(candidate_gcc_path):
+ gcc_path = candidate_gcc_path
+ break
+
+serenity_flags = [
+ '-D__serenity__',
+ '-D__unix__'
+]
+
+if gcc_path:
+ gcc_output = subprocess.check_output(
+ [gcc_path, '-E', '-Wp,-v', '-'],
+ stdin=subprocess.DEVNULL, stderr=subprocess.STDOUT
+ ).rstrip().decode('utf8').split("\n")
+
+ for line in gcc_output:
+ if not line.startswith(' '):
+ continue
+ include_path = line.lstrip()
+ if '/../Build/' in include_path:
+ continue
+ serenity_flags.extend(('-isystem', include_path))
+
+database = ycm_core.CompilationDatabase(f'Build/{serenity_arch}')
+
+
+def is_header_file(filename):
+ extension = os.path.splitext(filename)[1]
+ return extension in ['.h', '.hxx', '.hpp', '.hh']
+
+
+def find_corresponding_source_file(filename):
+ if is_header_file(filename):
+ basename = os.path.splitext(filename)[0]
+ for extension in SOURCE_EXTENSIONS:
+ replacement_file = basename + extension
+ if os.path.exists(replacement_file):
+ return replacement_file
+ return filename
+
+
+def startswith_any(string, prefixes):
+ for prefix in prefixes:
+ if string.startswith(prefix):
+ return True
+ return False
+
+
+def Settings(**kwargs):
+ if kwargs['language'] != 'cfamily':
+ return {}
+ # If the file is a header, try to find the corresponding source file and
+ # retrieve its flags from the compilation database if using one. This is
+ # necessary since compilation databases don't have entries for header files.
+ # In addition, use this source file as the translation unit. This makes it
+ # possible to jump from a declaration in the header file to its definition
+ # in the corresponding source file.
+ filename = find_corresponding_source_file(kwargs['filename'])
+
+ compilation_info = database.GetCompilationInfoForFile(filename)
+ if not compilation_info.compiler_flags_:
+ return {}
+
+ ignored_flags = [
+ '--sysroot',
+ '-fzero-call-used-regs=used-gpr',
+ ]
+
+ final_flags = [flag for flag in compilation_info.compiler_flags_ if not startswith_any(flag, ignored_flags)]
+ final_flags.extend(serenity_flags)
+
+ with open('/tmp/x', 'w') as fp:
+ import json
+ json.dump(final_flags, fp)
+
+ return {
+ 'flags': final_flags,
+ 'include_paths_relative_to_dir': DIR_OF_THIS_SCRIPT,
+ 'override_filename': filename
+ }
diff --git a/Documentation/VimConfiguration.md b/Documentation/VimConfiguration.md
new file mode 100644
index 0000000000..c5303990cb
--- /dev/null
+++ b/Documentation/VimConfiguration.md
@@ -0,0 +1,12 @@
+# Vim Project Configuration
+
+Vim can be configured to use the [YouCompleteMe](https://github.com/ycm-core/YouCompleteMe)
+plugin to provide code-completion.
+
+Once you've installed the YouCompleteMe plugin you should whitelist the
+configuration file that is part of the SerenityOS repository. You can
+do this by adding the following option to your `.vimrc` file:
+
+```vim
+let g:ycm_extra_conf_globlist = ['~/serenity/.ycm_extra_conf.py']
+```