summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYuka Takahashi <yukatkh@gmail.com>2017-05-23 18:39:08 +0000
committerYuka Takahashi <yukatkh@gmail.com>2017-05-23 18:39:08 +0000
commitba7f8116092b66ee165e2a2b817f85cbf537008c (patch)
tree5779e8761527753e2dfcf07b42db3b3265d8ddf5
parenta5e9f3fa65cccc0263789232ea0d770921ba6fb9 (diff)
[GSoC] Shell autocompletion for clang
Summary: This is a first patch for GSoC project, bash-completion for clang. To use this on bash, please run `source clang/utils/bash-autocomplete.sh`. bash-autocomplete.sh is code for bash-completion. Simple flag completion and path completion is available in this patch. Reviewers: teemperor, v.g.vassilev, ruiu, Bigcheese, efriedma Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D33237
-rw-r--r--clang/CMakeLists.txt4
-rw-r--r--clang/include/clang/Driver/Options.td1
-rw-r--r--clang/lib/Driver/Driver.cpp7
-rw-r--r--clang/test/Driver/autocomplete.c6
-rw-r--r--clang/utils/bash-autocomplete.sh14
-rw-r--r--llvm/include/llvm/Option/OptTable.h8
-rw-r--r--llvm/lib/Option/OptTable.cpp14
7 files changed, 54 insertions, 0 deletions
diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt
index 9e43a103b2b..c163a2b5042 100644
--- a/clang/CMakeLists.txt
+++ b/clang/CMakeLists.txt
@@ -359,6 +359,10 @@ if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
PATTERN "*.inc"
PATTERN "*.h"
)
+
+ install(PROGRAMS utils/bash-autocomplete.sh
+ DESTINATION share/clang
+ )
endif()
add_definitions( -D_GNU_SOURCE )
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index d812bd8ec03..4f1ea08dfe9 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -469,6 +469,7 @@ def arch__errors__fatal : Flag<["-"], "arch_errors_fatal">;
def arch : Separate<["-"], "arch">, Flags<[DriverOption]>;
def arch__only : Separate<["-"], "arch_only">;
def a : Joined<["-"], "a">;
+def autocomplete : Joined<["--"], "autocomplete=">;
def bind__at__load : Flag<["-"], "bind_at_load">;
def bundle__loader : Separate<["-"], "bundle_loader">;
def bundle : Flag<["-"], "bundle">;
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index f36deff5d73..bec4bf49281 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -1216,6 +1216,13 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
return false;
}
+ if (Arg *A = C.getArgs().getLastArg(options::OPT_autocomplete)) {
+ // Print out all options that start with a given argument. This is used for
+ // shell autocompletion.
+ llvm::outs() << llvm::join(Opts->findByPrefix(A->getValue()), " ") << '\n';
+ return false;
+ }
+
if (C.getArgs().hasArg(options::OPT_print_libgcc_file_name)) {
ToolChain::RuntimeLibType RLT = TC.GetRuntimeLibType(C.getArgs());
switch (RLT) {
diff --git a/clang/test/Driver/autocomplete.c b/clang/test/Driver/autocomplete.c
new file mode 100644
index 00000000000..94649f24373
--- /dev/null
+++ b/clang/test/Driver/autocomplete.c
@@ -0,0 +1,6 @@
+// RUN: %clang --autocomplete=-fsyn | FileCheck %s -check-prefix=FSYN
+// FSYN: -fsyntax-only
+// RUN: %clang --autocomplete=-s | FileCheck %s -check-prefix=STD
+// STD: -std={{.*}}-stdlib=
+// RUN: %clang --autocomplete=foo | not FileCheck %s -check-prefix=NONE
+// NONE: foo
diff --git a/clang/utils/bash-autocomplete.sh b/clang/utils/bash-autocomplete.sh
new file mode 100644
index 00000000000..a9067125147
--- /dev/null
+++ b/clang/utils/bash-autocomplete.sh
@@ -0,0 +1,14 @@
+# Please add "source /path/to/bash-autocomplete.sh" to your .bashrc to use this.
+_clang()
+{
+ local cur prev words cword flags
+ _init_completion -n : || return
+
+ flags=$( clang --autocomplete="$cur" )
+ if [[ "$flags" == "" || "$cur" == "" ]]; then
+ _filedir
+ else
+ COMPREPLY=( $( compgen -W "$flags" -- "$cur" ) )
+ fi
+}
+complete -F _clang clang
diff --git a/llvm/include/llvm/Option/OptTable.h b/llvm/include/llvm/Option/OptTable.h
index 390e52774fe..8a323a255ca 100644
--- a/llvm/include/llvm/Option/OptTable.h
+++ b/llvm/include/llvm/Option/OptTable.h
@@ -113,6 +113,14 @@ public:
return getInfo(id).MetaVar;
}
+ /// Find flags from OptTable which starts with Cur.
+ ///
+ /// \param [in] Cur - String prefix that all returned flags need
+ // to start with.
+ ///
+ /// \return The vector of flags which start with Cur.
+ std::vector<std::string> findByPrefix(StringRef Cur) const;
+
/// \brief Parse a single argument; returning the new argument and
/// updating Index.
///
diff --git a/llvm/lib/Option/OptTable.cpp b/llvm/lib/Option/OptTable.cpp
index 7eafb00855d..b00d21ec8f6 100644
--- a/llvm/lib/Option/OptTable.cpp
+++ b/llvm/lib/Option/OptTable.cpp
@@ -186,6 +186,20 @@ static unsigned matchOption(const OptTable::Info *I, StringRef Str,
return 0;
}
+std::vector<std::string> OptTable::findByPrefix(StringRef Cur) const {
+ std::vector<std::string> Ret;
+ for (const Info &In : OptionInfos.slice(FirstSearchableIndex)) {
+ if (!In.Prefixes)
+ continue;
+ for (int I = 0; In.Prefixes[I]; I++) {
+ std::string S = std::string(In.Prefixes[I]) + std::string(In.Name);
+ if (StringRef(S).startswith(Cur))
+ Ret.push_back(S);
+ }
+ }
+ return Ret;
+}
+
Arg *OptTable::ParseOneArg(const ArgList &Args, unsigned &Index,
unsigned FlagsToInclude,
unsigned FlagsToExclude) const {