[helpers] YCM helper

YouCompleteMe helper, updates the YCM config file once YCM-Generator
creates one for you. The steps are:

 * Install YCM / Generator
 * Inside Vim, on $LLVM_SRC, run :YcmGenerateConfig
 * Outside vim, with llvm-env on the same workdir run: llvm-ycm
 * Re-start vim, all is good

Why is this needed?

 1. YCM relies on .ycm_extra_conf.py to be precise and correct
 2. LLVM includes headers and libraries from both source and build dirs
 3. YCM-Generator has no idea about the build dir, so it uses /tmp

Note:

 * You will need to do this for each workdir, as the path has to be absolute
 * Don't use CMake's compilation_database.json, or header files won't work

Change-Id: If14008d96d7198060cb403439db55c234693c837
diff --git a/helpers/llvm-ycm b/helpers/llvm-ycm
new file mode 100755
index 0000000..55ffa50
--- /dev/null
+++ b/helpers/llvm-ycm
@@ -0,0 +1,102 @@
+#!/usr/bin/env perl
+
+use strict;
+use warnings;
+
+# This script updates the .ycm_extra_conf.py in $LLVM_SRC to work with
+# $LLVM_BLD's compile_commands.json and include/library paths.
+#
+# Syntax: llvm-ycm
+#
+# It will:
+#  * automatically detect $LLVM_SRC/BLD and change the paths.
+#  * also bail if those variables or .ycm_extra_conf.py don't exist.
+#  * exit successfully and silently if the file has already changed.
+
+my ($SRC, $BLD) = ($ENV{'LLVM_SRC'}, $ENV{'LLVM_BLD'});
+if (!$SRC || !$BLD || $ARGV[0] || ! -d $SRC || ! -d $BLD) {
+  die "Syntax: llvm-ycm\n\nUse llvm-env to set \$LLVM_SRC/BLD\n";
+}
+my ($ycm_conf, $compile_db) = (".ycm_extra_conf.py", "compile_commands.json");
+
+# If the file doesn't exist, don't try to guess the location of YCM-Generator
+# Vim can do that on its own, if properly setup. Educate the user.
+if (! -f "$SRC/$ycm_conf") {
+  die "$SRC/$ycm_conf doesn't exist!\n".
+      "You need to generate it using YCM-Generator.\n".
+      "\nTo install, run:\n".
+      "  mkdir -p ~/.vim/ext\n".
+      "  cd ~/.vim/ext\n".
+      "  git clone https://github.com/rdnetto/YCM-Generator.git\n".
+      "\nTo enable in vim, add this line to your .vimrc:\n".
+      "  set rtp+=~/.vim/ext/YCM-Generator\n".
+      "\nTo generate the file, open Vim inside your project and type:\n".
+      "  :YcmGenerateConfig\n".
+      "\nIf all goes well, you should have an $ycm_conf in $SRC\n";
+}
+
+# If the compile database doesn't exist, there's no point in even trying.
+# Educate the user.
+if (! -f "$BLD/$compile_db") {
+  die "$BLD/$compile_db doesn't exist!\n".
+      "You need to generate it using LLVM's CMake file.\n".
+      "\nTo create the compile database every build, add this option to CMake:\n".
+      "  -DCMAKE_EXPORT_COMPILE_COMMANDS=ON\n".
+      "\nRebuild, and check if the file is there, then run this script again.\n";
+}
+
+my @lines = ();
+my $bld_re = $BLD;
+$bld_re =~ s/\//\\\//g;
+
+# We need to open the file, buffer and close, so we can write back to the same
+# file again.
+open(FH, "$SRC/$ycm_conf") || die "Can't open file '$SRC/$ycm_conf': $!\n";
+foreach my $line (<FH>) {
+  # If the file has already been changed, let go.
+  if (&is_changed($line)) {
+    close FH;
+    exit(0);
+  }
+
+  # Change lines if needed
+  &change(\$line);
+
+  # Buffer
+  push @lines, $line;
+}
+close FH;
+
+# Now we write back and all should be good.
+open(FH, ">$SRC/$ycm_conf") || die "Can't open file '$SRC/$ycm_conf': $!\n";
+foreach my $line (@lines) {
+  print FH $line;
+}
+close FH;
+
+# All is good.
+exit(0);
+
+################################ Methods
+
+# is_changed($line): checks whether the line has been changed by this script.
+sub is_changed($) {
+  my ($line) = @_;
+  return ($line =~ /-I$bld_re/);
+}
+
+# change($$line): change the line in-place to make it work with YCM.
+sub change($) {
+  my ($line) = @_;
+  # from: -I/tmp/tmpUF9s_w/include
+  #   to: -I$LLVM_BLD/include
+  my $changed = ($$line =~ s/\/tmp\/\w+/$BLD/);
+  return if ($changed);
+
+  # Changing this line will make header and include files not work for
+  # completion, since they're not in the compilation database. Just using the
+  # whole lot of flags above works fine.
+  # from: compilation_database_folder = ''
+  #   to: compilation_database_folder = '$LLVM_BLD'
+  #$$line =~ s/(compilation_database_folder) = ''/$1 = '$BLD'/;
+}