Objective-C Code Completion in Vim

August 17, 2012

clang_complete is a plugin for Vim which provides automatic code completion in vim using the same technique (and library) as Xcode.

You need to do two things to configure it:

  1. Point it to your libclang.dylib
  2. Give it the compiler flags it needs to understand the code

Pointing to libclang.dylib

You can find Xcode's clang binary like so:

$ xcrun -find clang

The libclang.dylib we want will be in the lib path one level up from clang. For example, if xcrun prints this:

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang

The location to libclang.dylib is:

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib

In your .vimrc, you would then place the following:

let g:clang_library_path = '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib'

Finding the compiler flags

Use xcodebuild to run your build from the command line and redirect the output to a file. In the file, you will see some pretty heinous compile commands from which you can extract compiler commands. For example:

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -x objective-c++ -arch i386 -fmessage-length=0 -fobjc-gc -Wno-trigraphs -fpascal-strings -Os -Wno-missing-field-initializers -Wno-missing-prototypes -Wreturn-type -Wno-implicit-atomic-properties -Wno-receiver-is-weak -Wno-non-virtual-dtor -Wno-overloaded-virtual -Wno-exit-time-destructors -Wformat -Wno-missing-braces -Wparentheses -Wswitch -Wno-unused-function -Wno-unused-label -Wno-unused-parameter -Wunused-variable -Wunused-value -Wno-uninitialized -Wno-unknown-pragmas -Wno-shadow -Wno-four-char-constants -Wno-conversion -Wno-sign-compare -Wshorten-64-to-32 -Wno-newline-eof -Wno-selector -Wno-strict-selector-match -Wno-undeclared-selector -Wno-deprecated-implementations -Wno-arc-abi -Wc++11-extensions -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk -fasm-blocks -Wprotocol -Wdeprecated-declarations -Winvalid-offsetof -mmacosx-version-min=10.6 -g -fvisibility-inlines-hidden -Wno-sign-conversion "-DIBOutlet=__attribute__((iboutlet))" "-DIBOutletCollection(ClassName)=__attribute__((iboutletcollection(ClassName)))" "-DIBAction=void)__attribute__((ibaction)" -iquote /Users/jason/src/VimxCoder/build/VimxCode.build/Release/VimxCode.build/VimxCode-generated-files.hmap -I/Users/jason/src/VimxCoder/build/VimxCode.build/Release/VimxCode.build/VimxCode-own-target-headers.hmap -I/Users/jason/src/VimxCoder/build/VimxCode.build/Release/VimxCode.build/VimxCode-all-target-headers.hmap -iquote /Users/jason/src/VimxCoder/build/VimxCode.build/Release/VimxCode.build/VimxCode-project-headers.hmap -I/Users/jason/src/VimxCoder/build/Release/include -I/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include -I/Users/jason/src/VimxCoder/build/VimxCode.build/Release/VimxCode.build/DerivedSources/i386 -I/Users/jason/src/VimxCoder/build/VimxCode.build/Release/VimxCode.build/DerivedSources -F/Users/jason/src/VimxCoder/build/Release -include /var/folders/_7/bqndftw16pgc956b_m4r40800000gn/C/com.apple.Xcode.501/SharedPrecompiledHeaders/VimxCode-Prefix-gfcbppmysmvyzughyhahszroegov/VimxCode-Prefix.pch -MMD -MT dependencies -MF /Users/jason/src/VimxCoder/build/VimxCode.build/Release/VimxCode.build/Objects-normal/i386/EHNetbeansMessage.d --serialize-diagnostics /Users/jason/src/VimxCoder/build/VimxCode.build/Release/VimxCode.build/Objects-normal/i386/EHNetbeansMessage.dia -c /Users/jason/src/VimxCoder/VimxCode/EHNetbeansMessage.mm -o /Users/jason/src/VimxCoder/build/VimxCode.build/Release/VimxCode.build/Objects-normal/i386/EHNetbeansMessage.o

You can then:

  1. Remove the first shell word (clang and it's path).
  2. Remove the -o output-file argument at the end.
  3. Remove the path of the file being compiled.
  4. Store the rest in .clang_complete in the directory you start vim.

Verifying the flags work

If completion doesn't work or you have trouble with a particular file, you can test it with the following command:

xcrun clang `cat .clang_complete` /path/to/file.m

Libclang often offers basic suggestions when it can't parse a file. Usually, you'll notice that you are only seeing the methods from NSObject in the completion list, for example.

Using it

You can activate completion using ^XO, then using ^N and ^P to cycle through options. Use enter to select an option.

Tags: iOS vim objvimmer