aboutsummaryrefslogtreecommitdiff
path: root/helpers/llvm-ycm
blob: 55ffa5023ae37e4a0559ec4498bb8201e76257b2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
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'/;
}