-
Notifications
You must be signed in to change notification settings - Fork 2.8k
- I'm only getting [ID] suggestions... Where is printf ?
- The completions are just words from my buffer, how do I get the right functions listed?
- How do I configure YCM to always use semantic completion?
- I get a weird window at the top of my file when I use the semantic engine
- YCM shows errors on standard includes in cross-compiled C/C projects (clangd completer)
- I'm using clangd, how can I specify a per-project compilation database path?
- I'm using ccls, how can I specify a per-project compilation database path?
- I'm using clangd and it is inserting headers that I don't want
- After updating, Python completion no longer works
- I get a linker warning regarding libpython on macOS when compiling YCM
- It appears that YCM is not working
- YCM auto-inserts completion strings I don't want!
- I get a E227: mapping already exists for <blah> error when I start Vim
- I get 'GLIBC_2.XX' not found (required by libclang.so) when starting Vim
- I get LONG_BIT definition appears wrong for platform when compiling
- I see undefined symbol: clang_getCompletionFixIt in the server logs.
- I get Fatal Python error: PyThreadState_Get: no current thread on startup
- install.py says python must be compiled with --enable-framework. Wat?
- YCM does not read identifiers from my tags files
- CTRL-U in insert mode does not work while the completion menu is visible
- My CTRL-R mapping does not work while the completion menu is visible
- YCM conflicts with UltiSnips TAB key usage
- Snippets added with :UltiSnipsAddFiletypes do not appear in the popup menu
- I get an internal compiler error when installing
- I get weird errors when I press Ctrl-C in Vim
- Completion doesn't work with the C standard library headers
- When I start vim I get a runtime error saying R6034 An application has made an attempt to load the C runtime library incorrectly.
- On Windows I get E887: Sorry, this command is disabled, the Python's site module could not be loaded
- I can't complete Python packages in a virtual environment.
- I want to defer loading of YouCompleteMe until after Vim finishes booting
- YCM does not shut down when I quit Vim
- YCM does not work with my Anaconda Python setup
- TAB is already mapped to trigger completion in the command-line window
- Go completion: read-only files and directories in third_party/ycmd/third_party/go/pkg
- YCM crashes when using musl
- I get "Unknown compiler - C 17 filesystem library missing" on macOS
- I'm using rust with YCM and this causes breaks incremental builds of my project!
- How do I set the various options for my java project using jdt.ls
See the next question
TL;DR: Hit <Ctrl-Space>
. See https://github.com/ycm-core/YouCompleteMe#the-gycm_semantic_triggers-option
You are getting "identifier" completions (i.e. just words scanned from files), but you want "semantic" completion based on your code.
YCM only queries the semantic engine after a trigger. Usually, this is a
language-specific trigger like abc.
in many languages. The trigger here
is .
. This works well for most things, and the [ID]
(identifier - basically
words) suggestions fill the gap.
For some languages, like C, there are very many semantic options at the "top"
level scope, such as printf
etc. For these, you can type <Ctrl-Space>
in
insert mode to force YCM to request semantic completion from the semantic
engine.
To customise the triggers, see https://github.com/ycm-core/YouCompleteMe#the-gycm_semantic_triggers-option.
Here's an example that tells YCM to trigger semantic completion after
typing 3 "word" characters or an _
character.
This works well for C and similar languages:
let g:ycm_semantic_triggers = {
\ 'c,cpp,objc': [ 're!\w{3}', '_' ],
\ }
To request semantic completion for any word-character in a language, for example, JSON:
let g:ycm_semantic_triggers = {
\ 'json': [ 're!\w' ],
\ }
However, this is strongly discouraged.
See :help ycm_semantic_triggers.
TL;DR: set completeopt+=popup (see :help completeopt), or let g:ycm_add_preview_to_completeopt="popup"
. This will give you the same
information in a popup near the completion menu and will overall improve
performance as the information will be obtained on demand.
What you're seeing is Vim's preview
window. Vim uses it to show you extra
information about something if such information is available. YCM provides Vim
with such extra information. For instance, when you select a function in the
completion list, the preview
window will hold that function's prototype and
the prototypes of any overloads of the function. It will stay there after you
select the completion so that you can use the information about the parameters
and their types to write the function call.
If you would like this window to auto-close after you select a completion
string, set the g:ycm_autoclose_preview_window_after_completion
option to 1
in your vimrc
file. Similarly, the g:ycm_autoclose_preview_window_after_insertion
option can be set to close the preview
window after leaving insert mode.
If you don't want this window to ever show up, add set completeopt-=preview
to
your vimrc
. Also make sure that the g:ycm_add_preview_to_completeopt
option
is set to 0
.
This is because clangd doesn't know about your cross-compiler's includes. To solve this specify something like the following:
let g:ycm_clangd_args=['--query-driver=arm-none-eabi-g++']
If the cross-compiler isn't in your $PATH
, you'll need to use the full path to the compiler. If it's inconvenient to place this option in your .vimrc
, you can also use :h exrc
.
Using an extra conf file and passing the compilationDatabasePath
option to clangd.
For example, if your compilation database (compile_commands.json
) is in a dir
like build
under your project root, you could put something like this in a
.ycm_extra_conf.py
file in your project root:
DIR_OF_THIS_SCRIPT = p.abspath( p.dirname( __file__ ) )
def Settings( **kwargs ):
if language == 'cfamily':
cmake_commands = os.path.join( DIR_OF_THIS_SCRIPT, 'build', 'compile_commands.json')
if os.path.exists( cmake_commands ):
return {
'ls': {
'compilationDatabasePath': os.path.dirname( cmake_commands )
}
}
return None
See "I'm using clangd, how can I specify a per-project compilation database path?" and replace compilationDatabasePath
with compilationDatabaseDirectory
in the python snippet.
clangd/YCM will insert #include
directives for you if it can. This is very
cool.
However, clangd uses the "Include what you use" style of header insertion by default. This style of explicit inclusion of everything (even when something is provided by a transitive include) is not always to everyone's liking.
If you don't like this behaviour, you can control it by setting the
--header-insertion
option in g:ycm_clangd_args
. For example, to disable
it entirely set something like this:
let g:ycm_clangd_args = [ '--header-insertion=never' ]
Adapt this to add it if you already set g:ycmd_clangd_args
.
Sorry about that, it happens when switching Python versions, we think. Solution here: https://github.com/ycm-core/YouCompleteMe/issues/3765#issuecomment-695970983
If the warning is ld: warning: path '/usr/lib/libpython2.7.dylib' following -L not a directory
, then feel free to ignore it; it's caused by a limitation of
CMake and is not an issue. Everything should still work fine.
First, check this troubleshooting guide.
In Vim, run :messages
and carefully read the output. YCM will echo messages to
the message log if it encounters problems. It's likely you misconfigured
something and YCM is complaining about it.
Also, you may want to run the :YcmDebugInfo
command; it will make YCM spew out
various debugging information, including the YCM and ycmd logfile paths and
the compile flags for the current file if the file is a C-family language file
and you have compiled in Clang support. Logfiles can be opened in the editor
using the :YcmToggleLogs
command.
This could be some mappings that interfere with YCM's internal ones. Make
sure you don't have something mapped to <C-p>
, <C-x>
or <C-u>
(in insert
mode).
YCM never selects something for you; it just shows you a menu and the user has to explicitly select something. If something is being selected automatically, this means there's a bug or a misconfiguration somewhere.
This means that YCM tried to set up a key mapping but failed because you already
had something mapped to that key combination. The <blah>
part of the message
will tell you what was the key combination that failed.
Look in the Options section and see if any of the default mappings conflict with your own. Then change that option value to something else so that the conflict goes away.
Your system is too old for the precompiled binaries from llvm.org. Compile
Clang on your machine and then link against the libclang.so
you just produced.
See the full installation guide for help.
Look at the output of your CMake call. There should be a line in it like the
following (with .dylib
in place of .so
on macOS):
-- Found PythonLibs: /usr/lib/libpython2.7.so (Required is at least version "2.5")
That would be the correct output. An example of incorrect output would be the following:
-- Found PythonLibs: /usr/lib/libpython2.7.so (found suitable version "2.5.1", minimum required is "2.5")
Notice how there's an extra bit of output there, the found suitable version "<version>"
part, where <version>
is not the same as the version of the
dynamic library. In the example shown, the library is version 2.7 but the second
string is version 2.5.1
.
This means that CMake found one version of Python headers and a different version for the library. This is wrong. It can happen when you have multiple versions of Python installed on your machine.
You should probably add the following flags to your cmake call (again, dylib
instead of so
on macOS):
-DPYTHON_INCLUDE_DIR=/usr/include/python2.7 -DPYTHON_LIBRARY=/usr/lib/libpython2.7.so
This will force the paths to the Python include
directory and the Python library
to use. You may need to set these flags to something else, but you need to make
sure you use the same version of Python that your Vim binary is built against,
which is highly likely to be the system's default Python.
This means that the server is trying to load a version of libclang that is too
old. You need at least libclang 9.0.0. We recommend running the install.py
script without --system-libclang
or downloading the latest prebuilt binaries
from llvm.org when going through the full installation
guide.
This is caused by linking a static version of libpython
into ycmd's
ycm_core.so
. This leads to multiple copies of the Python interpreter loaded
when python
loads ycmd_core.so
and this messes up Python's global state.
The details aren't important.
The solution is that the version of Python linked and run against must be built
with either --enable-shared
or --enable-framework
(on OS X).
This is achieved as follows (NOTE: for macOS, replace --enable-shared
with --enable-framework
):
- When building Python from source:
./configure --enable-shared {options}
- When building Python from pyenv:
PYTHON_CONFIGURE_OPTS="--enable-shared" pyenv install {version}
See the previous answer for how to ensure your python is built to support dynamic modules.
First, put let g:ycm_collect_identifiers_from_tags_files = 1
in your vimrc.
Make sure you are using Exuberant Ctags to produce your tags
files since the only supported tag format is the Exuberant Ctags
format. The format from "plain" ctags is NOT supported. The
output of ctags --version
should list "Exuberant Ctags". See Universal
Ctags for a maintained version.
Ctags needs to be called with the --fields=+l
(that's a lowercase L
, not a
one) option because YCM needs the language:<lang>
field in the tags output.
NOTE: Exuberant Ctags by default sets language tag for
*.h
files as C++
. If you have a C (not C++) project, consider giving parameter
--langmap=c:.c.h
to ctags to see tags from *.h
files.
NOTE: macOS comes with "plain" ctags installed by default. brew install ctags
will get you the Exuberant Ctags version.
Also, make sure that your Vim tags
option is set correctly. See :h 'tags'
for
details. If you want to see which tag files YCM will read for a given buffer,
run :echo tagfiles()
with the relevant buffer active. Note that that function
will only list tag files that already exist.
YCM uses completefunc
completion mode to show suggestions and Vim disables
<C-U>
in that mode as a "feature." Sadly there's nothing I can do about this.
Vim prevents remapping of the <C-R>
key in all <C-X>
completion modes
(except the <C-X><C-N>
/<C-X><C-P>
mode which operates in the same mode as
<C-N>
/<C-P>
) and YCM uses the <C-X><C-U>
(completefunc
) mode for
completions. This means that adding <C-R>
to any of the g:ycm_key_list_*
options have no effect. You need to use another key.
YCM comes with support for UltiSnips (snippet suggestions in the popup menu),
but you'll have to change the UltiSnips mappings. See :h UltiSnips-triggers
in
Vim for details. You'll probably want to change some/all of the following
options:
g:UltiSnipsExpandTrigger
g:UltiSnipsJumpForwardTrigger
g:UltiSnipsJumpBackwardTrigger
For example, this works well:
" UltiSnips triggering :
" - ctrl-j to expand
" - ctrl-j to go to next tabstop
" - ctrl-k to go to previous tabstop
let g:UltiSnipsExpandTrigger = '<C-j>'
let g:UltiSnipsJumpForwardTrigger = '<C-j>'
let g:UltiSnipsJumpBackwardTrigger = '<C-k>'
For efficiency, YCM only fetches UltiSnips snippets in specific scenarios like
visiting a buffer or setting its filetype. You can force YCM to retrieve them by
manually triggering the FileType
autocommand:
:doautocmd FileType
This can be a problem on virtual servers with limited memory. A possible
solution is to add more swap memory. A more practical solution would be to force
the build script to run only one compile job at a time. You can do this by
setting the YCM_CORES
environment variable to 1
. Example:
YCM_CORES=1 ./install.py --clang-completer
Never use Ctrl-C
in Vim.
Using Ctrl-C
to exit insert mode in Vim is a bad idea. The main issue here is
that Ctrl-C
in Vim doesn't just leave insert mode, it leaves it without
triggering InsertLeave
autocommands (as per Vim docs). This is a bad idea and
is likely to break many other things and not just YCM.
Bottom line, if you use Ctrl-C
to exit insert mode in Vim, you're gonna have a
bad time.
If pressing <esc>
is too annoying (agreed, it is), we suggest mapping it to
something more convenient. On a QWERTY keyboard, a good pick for the <esc>
map
is inoremap jk <Esc>
. This is right on the home row, it's an incredibly rare
digraph in English and if you ever need to type those two chars in sequence in
insert mode, you just type j
, then wait 500ms, then type k
.
This is caused by an issue with libclang that only affects some operating
systems. Compiling with clang
the binary will use the correct default header
search paths but compiling with libclang.so
(which YCM uses) does not.
macOS is normally affected, but there's a workaround in YCM for that specific OS. If you're not running that OS but still have the same problem, continue reading.
The workaround is to call echo | clang -v -E -x c++ -
and look at the
paths under the #include <...> search starts here:
heading. You should take
those paths, prepend -isystem
to each individual path and append them all to
the list of flags you return from your Settings
function in your
.ycm_extra_conf.py
file.
See issue #303 for details.
When I start Vim I get a runtime error saying R6034 An application has made an attempt to load the C runtime library incorrectly.
CMake and other things seem to screw up the PATH with their own msvcrXX.dll versions. Add the following to the very top of your vimrc to remove these entries from the path.
python << EOF
import os
import re
path = os.environ['PATH'].split(';')
def contains_msvcr_lib(folder):
try:
for item in os.listdir(folder):
if re.match(r'msvcr\d+\.dll', item):
return True
except:
pass
return False
path = [folder for folder in path if not contains_msvcr_lib(folder)]
os.environ['PATH'] = ';'.join(path)
EOF
On Windows I get E887: Sorry, this command is disabled, the Python's site module could not be loaded
If you are running Vim on Windows with Python 2.7.11, this is likely caused by a bug. Follow this workaround or use a different version (Python 2.7.12 does not suffer from the bug).
This means that the Python used to run Jedi is not the Python of the virtual
environment you're in. To resolve this you should create a .ycm_extra_conf.py
file at the root of your project that sets the interpreter_path
option to the
Python of your virtual environment, e.g.
def Settings(**kwargs):
return {
'interpreter_path': '/path/to/virtual/env/bin/python'
}
See the Python Semantic Completion section for more details.
In recent versions of Vim, you can install YCM in a folder under
~/.vim/pack/*/opt
and then load it once the user is idle via an autocommand:
augroup load_ycm
autocmd!
autocmd CursorHold, CursorHoldI * :packadd YouCompleteMe
\ | autocmd! load_ycm
augroup END
YCM relies on the VimLeave
event to shut down the ycmd server. Some
plugins prevent this event from triggering by exiting Vim through an autocommand
without using the nested
keyword (see :h autocmd-nested
). You should
identify which plugin is responsible for the issue and report it to the plugin
author. Note that when this happens, ycmd will automatically shut itself
down after 30 minutes.
Anaconda is often incompatible with the pre-built libclang used by YCM
and therefore is not supported. The recommended way to solve this is to run
/path/to/real/python3 install.py
(for example /usr/bin/python3 install.py
).
If you want completion in Anaconda projects, point to the interpreter_path
option
in your .ycm_extra_conf.py
file to the path of your Anaconda Python e.g.
def Settings(**kwargs):
return {
'interpreter_path': '/path/to/anaconda/python'
}
See the Python Semantic Completion section for more details.
Vim automatically maps the key set by the wildchar
option, which is TAB
by
default, to complete commands in the command-line window. If you would prefer
using this key to cycle through YCM's suggestions without changing the value of
wildchar
, add the following to your vimrc:
autocmd CmdwinEnter * inoremap <expr><buffer> <TAB>
\ pumvisible() ? "\<C-n>" : "\<TAB>"
When YCM is installed with --go-completion
flag, it invokes go get golang.org/x/tools/[email protected]
. By default, go get
unsets the write bit from every tree element in $GOPATH/pkg
. See the details in issue 3721 and ycmd PR 1456.
To avoid it, if you use go version >=1.14
, set the GOFLAGS="$GOFLAGS -modcacherw"
. Here's a snippet for vim-plug:
Plug 'ycm-core/YouCompleteMe', { 'do': 'git submodule update --init --recursive && GOFLAGS=-modcacherw ./install.py --go-completer' }
YCM bundles clangd
for glibc systems, which gives the following error on musl-based systems:
libclang.so.11: mallinfo: symbol not found
To make YCM work on musl systems, do the following:
- Install clangd globally on your system.
rm /path/to/YCM/third_party/ycmd/third_party/clang/lib/libclang*
- Add
let g:ycm_clangd_binary_path='clangd'
to your.vimrc
file. - Recompile YCM without
--clang-completer
.
This is due to the old version of your macOS. If the system can't be updated for some reason, then homebrew can be used to install the necessary up-to-date build tools:
brew install cmake python llvm
llvm is keg-only, which means it was not symlinked into the homebrew installation directory, because macOS already provides this software and installing another version in parallel can cause all kinds of trouble.
To force llvm symlinks:
brew link -f llvm
Note that homebrew's llvm ships with its own libc++ but use the system's libc++ by default.
To use the bundled libc++ we need to specify the corresponding flags to the linker:
export LDFLAGS="-L$(brew --prefix)/opt/llvm/lib -Wl,-rpath,$(brew --prefix)/opt/llvm/lib"
Then install using the homebrew llvm clang
and clang++
:
CC=$(brew --prefix)/bin/clang CXX=$(brew --prefix)/bin/clang++ ./install.py --clangd-completer --verbose
TL;DR - set g:ycm_rust_toolchain_root
to point at your rust toolchain, and
ensure that it includes a compatible version of rust-analyzer
.
The reason for this is... reasons. We're not going to go into them because they are tedious and annoying.
See https://github.com/ycm-core/YouCompleteMe/issues/4012 for some more info.
AKA "How do I set the java home directory (i.e. java version) used for gradle?"
The eclipse.jdt.ls project provides the list of options in the form of this page: https://github.com/eclipse-jdtls/eclipse.jdt.ls/wiki/Running-the-JAVA-LS-server-from-the-command-line#initialize-request
Essentially you reverse-engineer that graph of objects into a string like java.import.gradle.java.home
and set the values as follows:
def Settings(**kwargs):
if kwargs['language'] == 'java':
return {
'ls': { 'settings': {
'java.import.gradle.java.home': '/etc/alternatives/java_sdk_11',
} }
}
Repeat for any of the other Preferences. The rule is basically that the ls
dictionary is merged with the 'initializationOptions', and anything under 'settings' is read either as a dotted name, or as a fully qualified object. settings
must be a dict (despite what the documentation says).
So the above is equivalent to:
def Settings(**kwargs):
if kwargs['language'] == 'java':
return {
'ls': { 'settings': {
'java': { 'import': { 'gradle' { 'java': { 'home': '/etc/alternatives/java_sdk_11' } } } }
} }
}
The later is preferred, as that's actually what JDT.LS documents, but the former is a lot easier to write and maintain.