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.