From 5ad292328ad908b52e61f406b1da93a02cadcc10 Mon Sep 17 00:00:00 2001 From: Mahmoud Al-Qudsi Date: Mon, 22 Oct 2018 23:53:20 -0500 Subject: [PATCH] Add dynamic clang completions via clang --autocomplete Use clang/clang++'s own autocompletion support to complete arguments. It is rather convoluted as clang generates autocompletions for a portion of the current token rather than the entire token, e.g. while `--st` will autocomplete to `--std=` (which is fine by fish), `--std=g` will autocomplete to `gnu...` without the leading `--std=` which breaks fish' support for the completion. Additionally, on systems where clang/clang++ is the system compiler (such as FreeBSD), it is very often for users to invoke a newer version of clang/clang++ installed as clang[++]-NN instead of clang. Using a monkey-patched version of `complete -p` to support that without breaking (future) completions for commands like `clang-format`. Closes #4174. --- CHANGELOG.md | 1 + share/completions/clang++.fish | 7 +++++++ share/completions/clang.fish | 11 +++++++++++ share/functions/__fish_clang_complete.fish | 16 ++++++++++++++++ 4 files changed, 35 insertions(+) create mode 100644 share/completions/clang++.fish create mode 100644 share/completions/clang.fish create mode 100644 share/functions/__fish_clang_complete.fish diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ca7c0655..380dffff0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -98,6 +98,7 @@ fish 3.0 is a major release which brings with it both improvements in functional - Added completions for - `bd` (#4472) - `bower` + - `clang` and `clang++` (#4174) - `configure` (autoconf only) - `doas` (#5196) - `hjson` diff --git a/share/completions/clang++.fish b/share/completions/clang++.fish new file mode 100644 index 000000000..7b7087c3a --- /dev/null +++ b/share/completions/clang++.fish @@ -0,0 +1,7 @@ +# Multiple versions are often installed as clang++, clang++-7, clang++-8, etc. +# They won't be autoloaded, but once clang++ is used once, they'll gain completions too. +# This could potentially be moved to __fish_config_interactive.fish in the future. + +complete -p '*clang++*' -n '__fish_should_complete_switches' -xa '(__fish_clang_complete)' +complete -p '*clang++*' -n 'not __fish_should_complete_switches' \ + -xa '(__fish_complete_suffix \'{.o,.out,.c,.cpp,.so,.dylib}\')' diff --git a/share/completions/clang.fish b/share/completions/clang.fish new file mode 100644 index 000000000..b7879550e --- /dev/null +++ b/share/completions/clang.fish @@ -0,0 +1,11 @@ +# Multiple versions are often installed as clang, clang-7, clang-8, etc. +# They won't be autoloaded, but once clang++ is used once, they'll gain completions too. +# This could potentially be moved to __fish_config_interactive.fish in the future. + +# This pattern unfortunately matches clang-format, etc. as well. +complete -p '*clang*' -n '__fish_should_complete_switches' -xa '(__fish_clang_complete)' +complete -c 'clang' -n 'not __fish_should_complete_switches' \ + -xa "(__fish_complete_suffix '{.o,.out,.c,.cpp,.so,.dylib}')" +# again but without the -x this time for the pattern-matched completion +complete -p '*clang*' -n 'not __fish_should_complete_switches' \ + -a "(__fish_complete_suffix '{.o,.out,.c,.cpp,.so,.dylib}')" diff --git a/share/functions/__fish_clang_complete.fish b/share/functions/__fish_clang_complete.fish new file mode 100644 index 000000000..188799919 --- /dev/null +++ b/share/functions/__fish_clang_complete.fish @@ -0,0 +1,16 @@ +# This function is compatible with clang, clang++, and variations thereof, and is shared +# by clang.fish and clang++.fish. +# We dynamically query the head at `(commandline -o)[1]` to get the correct completions. +function __fish_clang_complete + # If the result is for a value, clang only prints the value, so completions + # for `-std=` print `c++11` and not `-std=c++11` like we need. See #4174. + set -l prefix (commandline -ct | string replace -fr -- '^(.*=)[^=]*' '$1') + + # Don't hard-code the name of the clang binary + set -l clang (commandline -o)[1] + # first get the completions from clang, with the prefix separated from the value by a comma + $clang --autocomplete=(commandline -ct | string replace -- "$prefix" "$prefix,") 2>/dev/null | + # and put it in a format that fish understands + string replace -r -- '^([^ ]+)\s*(.*)' "$prefix\$1\t\$2" +end +