You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@quickstep.apache.org by Marc Spehlmann <sp...@gmail.com> on 2016/07/21 20:21:42 UTC
vim -> IDE
Hello Quicksteppers,
If you use vim, I recommend trying the plugin YouCompleteMe (
https://github.com/Valloric/YouCompleteMe). It offers code completion and
it works well out of the box with quickstep. I'll give a quick intro on how
to get it set up:
1 Requirements
- clang
- vim 7.3.8+
- ruby
2 Installation
- I used Vundle (https://github.com/VundleVim/Vundle.vim), a plugin
manager for vim. There is a set up guide on the README. It was easy to get
started and I tried another couple plugins. One thing I noticed was that
sometimes vundle would not install correcly (with CommandT, for example) so
I had to manually install by going to ~/.vim/bundle/my-plugin and following
the README there.
My vimrc looks like:
```
" Vundle Config
set nocompatible " be iMproved, required
filetype off " required
" set the runtime path to include Vundle and initialize
set rtp+=~/.vim/bundle/Vundle.vim
call vundle#begin()
" alternatively, pass a path where Vundle should install plugins
"call vundle#begin('~/some/path/here')
" let Vundle manage Vundle, required
Plugin 'VundleVim/Vundle.vim'
Plugin 'Valloric/YouCompleteMe'
Plugin 'wincent/command-t'
Plugin 'rdnetto/YCM-Generator'
" All of your Plugins must be added before the following line
call vundle#end() " required
filetype plugin indent on " required
" To ignore plugin indent changes, instead use:
"filetype plugin on
"
" Brief help
" :PluginList - lists configured plugins
" :PluginInstall - installs plugins; append `!` to update or just
:PluginUpdate
" :PluginSearch foo - searches for foo; append `!` to refresh local cache
" :PluginClean - confirms removal of unused plugins; append `!` to
auto-approve removal
"
" see :h vundle for more details or wiki for FAQ
" My config
```
- Then I modified quickstep's CMakeList.txt, adding a line to create a
compilation commands database:
`set( CMAKE_EXPORT_COMPILE_COMMANDS 1 )`
-Recompile quickstep, it will generate a json file in the build folder
with the database
-Add a custom YCM config file to the root quickstep directory. Here's the
one I used (note the !!! CHANGE THIS comments)
```
import os
import os.path
import fnmatch
import logging
import ycm_core
# !!! CHANGE THIS
# I used this before I found out about the flags database. If you
# generate it, you will not need any flags:
flags = [
'-DQUICKSTEP_DEBUG',
'-DQUICKSTEP_ENABLE_VECTOR_COPY_ELISION_SELECTION',
'-DQUICKSTEP_ENABLE_VECTOR_PREDICATE_SHORT_CIRCUIT',
'-DYY_NO_UNISTD_H',
'-D_ISOC11_SOURCE',
'-I',
'/Users/mspehlmann/code/incubator-quickstep',
'-I',
'/Users/mspehlmann/code/incubator-quickstep/build',
'-isystem',
'/Users/mspehlmann/code/incubator-quickstep/third_party/protobuf/src',
'-isystem',
'/Users/mspehlmann/code/incubator-quickstep/third_party/googletest/googletest/include',
'-I',
'/Users/mspehlmann/code/incubator-quickstep/third_party/benchmark/include',
'-I',
'/Users/mspehlmann/code/incubator-quickstep/build/third_party/gflags/include',
'-I',
'/Users/mspehlmann/code/incubator-quickstep/third_party/glog/src',
'-I',
'/Users/mspehlmann/code/incubator-quickstep/build/third_party',
'-I',
'/Users/mspehlmann/code/incubator-quickstep/third_party/re2',
'-I',
'/Users/mspehlmann/code/incubator-quickstep/third_party/tmb/include ',
'-std=c++14',
'-Wall',
'-pedantic',
'-Werror',
'-march=native',
'-Wno-return-type-c-linkage',
'-g'
]
SOURCE_EXTENSIONS = [
'.cpp',
'.cxx',
'.cc',
'.c',
'.m',
'.mm'
]
HEADER_EXTENSIONS = [
'.h',
'.hxx',
'.hpp',
'.hh'
]
# !!! CHANGE THIS
compilation_database_folder =
'/Users/mspehlmann/code/incubator-quickstep/build'
if os.path.exists( compilation_database_folder ):
database = ycm_core.CompilationDatabase( compilation_database_folder )
else:
database = None
SOURCE_EXTENSIONS = [ '.cpp', '.cxx', '.cc', '.c', '.m', '.mm' ]
def DirectoryOfThisScript():
return os.path.dirname( os.path.abspath( __file__ ) )
def MakeRelativePathsInFlagsAbsolute( flags, working_directory ):
if not working_directory:
return list( flags )
new_flags = []
make_next_absolute = False
path_flags = [ '-isystem', '-I', '-iquote', '--sysroot=' ]
for flag in flags:
new_flag = flag
if make_next_absolute:
make_next_absolute = False
if not flag.startswith( '/' ):
new_flag = os.path.join( working_directory, flag )
for path_flag in path_flags:
if flag == path_flag:
make_next_absolute = True
break
if flag.startswith( path_flag ):
path = flag[ len( path_flag ): ]
new_flag = path_flag + os.path.join( working_directory, path )
break
if new_flag:
new_flags.append( new_flag )
return new_flags
def IsHeaderFile( filename ):
extension = os.path.splitext( filename )[ 1 ]
return extension in [ '.h', '.hxx', '.hpp', '.hh' ]
def GetCompilationInfoForFile( filename ):
# The compilation_commands.json file generated by CMake does not have
entries
# for header files. So we do our best by asking the db for flags for a
# corresponding source file, if any. If one exists, the flags for that
file
# should be good enough.
if IsHeaderFile( filename ):
basename = os.path.splitext( filename )[ 0 ]
for extension in SOURCE_EXTENSIONS:
replacement_file = basename + extension
if os.path.exists( replacement_file ):
compilation_info = database.GetCompilationInfoForFile(
replacement_file )
if compilation_info.compiler_flags_:
return compilation_info
return None
return database.GetCompilationInfoForFile( filename )
def FlagsForFile( filename, **kwargs ):
if database:
# Bear in mind that compilation_info.compiler_flags_ does NOT return a
# python list, but a "list-like" StringVec object
compilation_info = GetCompilationInfoForFile( filename )
if not compilation_info:
return None
final_flags = MakeRelativePathsInFlagsAbsolute(
compilation_info.compiler_flags_,
compilation_info.compiler_working_dir_ )
else:
relative_to = DirectoryOfThisScript()
global flags
final_flags = MakeRelativePathsInFlagsAbsolute( flags, relative_to )
return {
'flags': final_flags,
'do_cache': True
}
```
- YouCompleteMe also suggests setting a global config file. There's a good
way to do this via this blog post (
https://jonasdevlieghere.com/a-better-youcompleteme-config/)
- Once you have the configuration in the root quickstep folder, and have
generated the flags database or modified the flags list, open a quickstep
source file in vim, type :YcmDebugInfo and you should get a good diagnostic
output
If you use vim, this is likely to be useful.
Best of luck,
Marc
PS
clion might also be a good option. They offer free licenses to open source
projects.
Re: vim -> IDE
Posted by Navneet Potti <na...@gmail.com>.
YCM is not bad, but have you used rtags <https://github.com/Andersbakken/rtags>? It’s by far the best C++ code navigation engine there is (beating out most IDEs I’ve tried, including OS X).
And not to get us started on the vim vs emacs flame war, but I’m a big fan of Spacemacs <https://github.com/syl20bnr/spacemacs> which brings together all the goodness of Emacs (extensibility!) and vim (modal editing).
> On Jul 21, 2016, at 15:21, Marc Spehlmann <sp...@gmail.com> wrote:
>
> Hello Quicksteppers,
>
> If you use vim, I recommend trying the plugin YouCompleteMe (
> https://github.com/Valloric/YouCompleteMe). It offers code completion and
> it works well out of the box with quickstep. I'll give a quick intro on how
> to get it set up:
>
> 1 Requirements
> - clang
> - vim 7.3.8+
> - ruby
>
> 2 Installation
> - I used Vundle (https://github.com/VundleVim/Vundle.vim), a plugin
> manager for vim. There is a set up guide on the README. It was easy to get
> started and I tried another couple plugins. One thing I noticed was that
> sometimes vundle would not install correcly (with CommandT, for example) so
> I had to manually install by going to ~/.vim/bundle/my-plugin and following
> the README there.
>
> My vimrc looks like:
> ```
> " Vundle Config
> set nocompatible " be iMproved, required
> filetype off " required
>
> " set the runtime path to include Vundle and initialize
> set rtp+=~/.vim/bundle/Vundle.vim
> call vundle#begin()
> " alternatively, pass a path where Vundle should install plugins
> "call vundle#begin('~/some/path/here')
>
> " let Vundle manage Vundle, required
> Plugin 'VundleVim/Vundle.vim'
> Plugin 'Valloric/YouCompleteMe'
> Plugin 'wincent/command-t'
> Plugin 'rdnetto/YCM-Generator'
> " All of your Plugins must be added before the following line
> call vundle#end() " required
> filetype plugin indent on " required
> " To ignore plugin indent changes, instead use:
> "filetype plugin on
> "
> " Brief help
> " :PluginList - lists configured plugins
> " :PluginInstall - installs plugins; append `!` to update or just
> :PluginUpdate
> " :PluginSearch foo - searches for foo; append `!` to refresh local cache
> " :PluginClean - confirms removal of unused plugins; append `!` to
> auto-approve removal
> "
> " see :h vundle for more details or wiki for FAQ
>
> " My config
> ```
> - Then I modified quickstep's CMakeList.txt, adding a line to create a
> compilation commands database:
> `set( CMAKE_EXPORT_COMPILE_COMMANDS 1 )`
> -Recompile quickstep, it will generate a json file in the build folder
> with the database
> -Add a custom YCM config file to the root quickstep directory. Here's the
> one I used (note the !!! CHANGE THIS comments)
>
> ```
> import os
> import os.path
> import fnmatch
> import logging
> import ycm_core
>
> # !!! CHANGE THIS
> # I used this before I found out about the flags database. If you
> # generate it, you will not need any flags:
> flags = [
> '-DQUICKSTEP_DEBUG',
> '-DQUICKSTEP_ENABLE_VECTOR_COPY_ELISION_SELECTION',
> '-DQUICKSTEP_ENABLE_VECTOR_PREDICATE_SHORT_CIRCUIT',
> '-DYY_NO_UNISTD_H',
> '-D_ISOC11_SOURCE',
> '-I',
> '/Users/mspehlmann/code/incubator-quickstep',
> '-I',
> '/Users/mspehlmann/code/incubator-quickstep/build',
> '-isystem',
> '/Users/mspehlmann/code/incubator-quickstep/third_party/protobuf/src',
> '-isystem',
>
> '/Users/mspehlmann/code/incubator-quickstep/third_party/googletest/googletest/include',
> '-I',
>
> '/Users/mspehlmann/code/incubator-quickstep/third_party/benchmark/include',
> '-I',
>
> '/Users/mspehlmann/code/incubator-quickstep/build/third_party/gflags/include',
> '-I',
> '/Users/mspehlmann/code/incubator-quickstep/third_party/glog/src',
> '-I',
> '/Users/mspehlmann/code/incubator-quickstep/build/third_party',
> '-I',
> '/Users/mspehlmann/code/incubator-quickstep/third_party/re2',
> '-I',
> '/Users/mspehlmann/code/incubator-quickstep/third_party/tmb/include ',
> '-std=c++14',
> '-Wall',
> '-pedantic',
> '-Werror',
> '-march=native',
> '-Wno-return-type-c-linkage',
> '-g'
> ]
>
> SOURCE_EXTENSIONS = [
> '.cpp',
> '.cxx',
> '.cc',
> '.c',
> '.m',
> '.mm'
> ]
>
> HEADER_EXTENSIONS = [
> '.h',
> '.hxx',
> '.hpp',
> '.hh'
> ]
> # !!! CHANGE THIS
> compilation_database_folder =
> '/Users/mspehlmann/code/incubator-quickstep/build'
>
> if os.path.exists( compilation_database_folder ):
> database = ycm_core.CompilationDatabase( compilation_database_folder )
> else:
> database = None
>
> SOURCE_EXTENSIONS = [ '.cpp', '.cxx', '.cc', '.c', '.m', '.mm' ]
>
> def DirectoryOfThisScript():
> return os.path.dirname( os.path.abspath( __file__ ) )
>
>
> def MakeRelativePathsInFlagsAbsolute( flags, working_directory ):
> if not working_directory:
> return list( flags )
> new_flags = []
> make_next_absolute = False
> path_flags = [ '-isystem', '-I', '-iquote', '--sysroot=' ]
> for flag in flags:
> new_flag = flag
>
> if make_next_absolute:
> make_next_absolute = False
> if not flag.startswith( '/' ):
> new_flag = os.path.join( working_directory, flag )
>
> for path_flag in path_flags:
> if flag == path_flag:
> make_next_absolute = True
> break
>
> if flag.startswith( path_flag ):
> path = flag[ len( path_flag ): ]
> new_flag = path_flag + os.path.join( working_directory, path )
> break
>
> if new_flag:
> new_flags.append( new_flag )
> return new_flags
>
>
> def IsHeaderFile( filename ):
> extension = os.path.splitext( filename )[ 1 ]
> return extension in [ '.h', '.hxx', '.hpp', '.hh' ]
>
>
> def GetCompilationInfoForFile( filename ):
> # The compilation_commands.json file generated by CMake does not have
> entries
> # for header files. So we do our best by asking the db for flags for a
> # corresponding source file, if any. If one exists, the flags for that
> file
> # should be good enough.
> if IsHeaderFile( filename ):
> basename = os.path.splitext( filename )[ 0 ]
> for extension in SOURCE_EXTENSIONS:
> replacement_file = basename + extension
> if os.path.exists( replacement_file ):
> compilation_info = database.GetCompilationInfoForFile(
> replacement_file )
> if compilation_info.compiler_flags_:
> return compilation_info
> return None
> return database.GetCompilationInfoForFile( filename )
>
>
> def FlagsForFile( filename, **kwargs ):
> if database:
> # Bear in mind that compilation_info.compiler_flags_ does NOT return a
> # python list, but a "list-like" StringVec object
> compilation_info = GetCompilationInfoForFile( filename )
> if not compilation_info:
> return None
>
> final_flags = MakeRelativePathsInFlagsAbsolute(
> compilation_info.compiler_flags_,
> compilation_info.compiler_working_dir_ )
>
> else:
> relative_to = DirectoryOfThisScript()
> global flags
> final_flags = MakeRelativePathsInFlagsAbsolute( flags, relative_to )
>
> return {
> 'flags': final_flags,
> 'do_cache': True
> }
> ```
> - YouCompleteMe also suggests setting a global config file. There's a good
> way to do this via this blog post (
> https://jonasdevlieghere.com/a-better-youcompleteme-config/)
> - Once you have the configuration in the root quickstep folder, and have
> generated the flags database or modified the flags list, open a quickstep
> source file in vim, type :YcmDebugInfo and you should get a good diagnostic
> output
>
> If you use vim, this is likely to be useful.
>
> Best of luck,
> Marc
>
> PS
> clion might also be a good option. They offer free licenses to open source
> projects.