]>
git.rmz.io Git - dotfiles.git/blob - vim/ycm_extra_conf.py
1 # https://github.com/Valloric/ycmd/blob/master/cpp/ycm/.ycm_extra_conf.py
2 # https://jonasdevlieghere.com/a-better-youcompleteme-config/
3 # https://github.com/arximboldi/dotfiles/blob/master/emacs/.ycm_extra_conf.py
15 '-isystem', '/usr/include',
16 '-isystem', '/usr/local/include',
26 # '-Wno-variadic-macros',
48 # Implementation taken from
49 # https://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#Python
50 def levenshtein(s
, t
):
51 ''' From Wikipedia article; Iterative with two matrix rows. '''
53 elif len(s
) == 0: return len(t
)
54 elif len(t
) == 0: return len(s
)
55 v0
= [None] * (len(t
) + 1)
56 v1
= [None] * (len(t
) + 1)
57 for i
in range(len(v0
)):
59 for i
in range(len(s
)):
61 for j
in range(len(t
)):
62 cost
= 0 if s
[i
] == t
[j
] else 1
63 v1
[j
+ 1] = min(v1
[j
] + 1, v0
[j
+ 1] + 1, v0
[j
] + cost
)
64 for j
in range(len(v0
)):
69 def generate_qt_flags():
70 flags
= ['-isystem', '/usr/include/qt/']
71 for p
in glob('/usr/include/qt/*/'):
72 flags
+= ['-isystem', p
]
76 def find_similar_file_in_database(dbpath
, filename
):
78 logging
.info("Trying to find some file close to: " + filename
)
79 db
= json
.load(open(dbpath
))
81 best_distance
= 1 << 31
83 entry_filename
= os
.path
.normpath(
84 os
.path
.join(entry
["directory"], entry
["file"]))
85 distance
= levenshtein(str(filename
), str(entry_filename
))
86 if distance
< best_distance
:
87 best_filename
= entry_filename
88 best_distance
= distance
91 def ok_compilation_info(info
):
92 return bool(info
.compiler_flags_
)
94 def get_compilation_info_for_file(dbpath
, database
, filename
):
95 info
= database
.GetCompilationInfoForFile(filename
)
96 if ok_compilation_info(info
):
97 logging
.info("Flags for file where found in database: " + filename
)
100 logging
.info("Flags for file not found in database: " + filename
)
101 basename
= os
.path
.splitext(filename
)[0]
102 for extension
in SOURCE_EXTENSIONS
:
103 replacement_file
= basename
+ extension
104 logging
.info("Trying to replace extension with: " + extension
)
105 info
= database
.GetCompilationInfoForFile(replacement_file
)
106 if ok_compilation_info(info
):
107 logging
.info("Replacing header with: " + replacement_file
)
109 replacement_file
= find_similar_file_in_database(dbpath
, filename
)
110 logging
.info("Replacing header with: " + replacement_file
)
111 return database
.GetCompilationInfoForFile(replacement_file
)
114 def find_nearest_compilation_database(root
='.'):
115 dirs
= glob(root
+ '/*/compile_commands.json', recursive
=True)
120 logging
.info("Multiple compilation databases found!")
122 logging
.info("Selecting first: %s" % (dir))
125 parent
= os
.path
.dirname(os
.path
.abspath(root
))
127 raise RuntimeError("Could not find compile_commands.json")
128 return find_nearest_compilation_database(parent
)
131 def find_nearest(path
, target
):
133 os
.path
.join(path
, target
),
134 os
.path
.join(path
, 'build', target
),
135 os
.path
.join(path
, 'output', target
),
137 for candidate
in candidates
:
138 if os
.path
.isfile(candidate
) or os
.path
.isdir(candidate
):
139 logging
.info("Found nearest " + target
+ " at " + candidate
)
141 parent
= os
.path
.dirname(os
.path
.abspath(path
))
143 raise RuntimeError("Could not find " + target
)
144 return find_nearest(parent
, target
)
147 def make_relative_paths_in_flags_absolute(flags
, working_directory
):
148 if not working_directory
:
151 make_next_absolute
= False
152 path_flags
= [ '-isystem', '-I', '-iquote', '--sysroot=' ]
155 if make_next_absolute
:
156 make_next_absolute
= False
157 if not flag
.startswith('/'):
158 new_flag
= os
.path
.join(working_directory
, flag
)
159 for path_flag
in path_flags
:
160 if flag
== path_flag
:
161 make_next_absolute
= True
163 if flag
.startswith(path_flag
):
164 path
= flag
[ len(path_flag
): ]
165 new_flag
= path_flag
+ os
.path
.join(working_directory
, path
)
168 new_flags
.append(new_flag
)
172 def flags_for_include(root
):
174 include_path
= find_nearest(root
, 'include')
176 for dirroot
, dirnames
, filenames
in os
.walk(include_path
):
177 for dir_path
in dirnames
:
178 real_path
= os
.path
.join(dirroot
, dir_path
)
179 flags
= flags
+ ["-I" + real_path
]
181 except Exception as err
:
182 logging
.info("Error while looking flags for includes in root: " + root
)
187 def flags_for_compilation_database(root
, filename
):
189 compilation_db_path
= find_nearest_compilation_database(root
)
190 compilation_db_dir
= os
.path
.dirname(compilation_db_path
)
191 logging
.info("Set compilation database directory to " + compilation_db_dir
)
192 compilation_db
= ycm_core
.CompilationDatabase(compilation_db_dir
)
193 if not compilation_db
:
194 logging
.info("Compilation database file found but unable to load")
196 compilation_info
= get_compilation_info_for_file(
197 compilation_db_path
, compilation_db
, filename
)
198 if not compilation_info
:
199 logging
.info("No compilation info for " + filename
+ " in compilation database")
201 return make_relative_paths_in_flags_absolute(
202 compilation_info
.compiler_flags_
,
203 compilation_info
.compiler_working_dir_
)
204 except Exception as err
:
205 logging
.info("Error while trying to get flags for " + filename
+ " in compilation database")
210 def FlagsForFile(filename
, **kwargs
):
211 client_data
= kwargs
['client_data']
212 root
= client_data
['getcwd()']
214 compilation_db_flags
= flags_for_compilation_database(root
, filename
)
215 if compilation_db_flags
:
216 final_flags
= compilation_db_flags
218 final_flags
= BASE_FLAGS
219 include_flags
= flags_for_include(root
)
221 final_flags
= final_flags
+ include_flags
223 final_flags
+= generate_qt_flags()
226 '-I', root
+ '/include',
229 'flags': final_flags
+ EXTRA_FLAGS
,