30

Has anyone had any luck getting fish shell to work with google's gcloud command line tools? I'm not an expert in Fish script but these are the two files gcloud needs to run (which work fine use Fish's bash mode). Fish doesn't allow you to source bash files from what I understand so these would need to be converted to Fish script?

path.bash

script_link="$( readlink "$BASH_SOURCE" )" || script_link="$BASH_SOURCE"
apparent_sdk_dir="${script_link%/*}"
if [ "$apparent_sdk_dir" == "$script_link" ]; then
  apparent_sdk_dir=.
fi
sdk_dir="$( command cd -P "$apparent_sdk_dir" && pwd -P )"
bin_path="$sdk_dir/bin"
export PATH=$bin_path:$PATH

path.completion

_python_argcomplete() {
    local IFS=''
    COMPREPLY=( $(IFS="$IFS"                   COMP_LINE="$COMP_LINE"                   COMP_POINT="$COMP_POINT"                   _ARGCOMPLETE_COMP_WORDBREAKS="$COMP_WORDBREAKS"                   _ARGCOMPLETE=1                   "$1" 8>&1 9>&2 1>/dev/null 2>/dev/null) )
    if [[ $? != 0 ]]; then
        unset COMPREPLY
    fi
}
complete -o default -F _python_argcomplete "gcloud"

_completer() {
    command=$1
    name=$2
    eval '[[ "$'"${name}"'_COMMANDS" ]] || '"${name}"'_COMMANDS="$('"${command}"')"'
    set -- $COMP_LINE
    shift
    while [[ $1 == -* ]]; do
          shift
    done
    [[ $2 ]] && return
    grep -q "${name}\s*$" <<< $COMP_LINE &&
        eval 'COMPREPLY=($'"${name}"'_COMMANDS)' &&
        return
    [[ "$COMP_LINE" == *" " ]] && return
    [[ $1 ]] &&
        eval 'COMPREPLY=($(echo "$'"${name}"'_COMMANDS" | grep ^'"$1"'))'
}

unset bq_COMMANDS
_bq_completer() {
    _completer "CLOUDSDK_COMPONENT_MANAGER_DISABLE_UPDATE_CHECK=1 bq help | grep '^[^ ][^ ]*  ' | sed 's/ .*//'" bq
}

unset gsutil_COMMANDS
_gsutil_completer() {
    _completer "CLOUDSDK_COMPONENT_MANAGER_DISABLE_UPDATE_CHECK=1 gsutil help | sed /Additional/q | grep '^  ' | sed -e 's/^  //' -e 's/ .*//'" gsutil
}

unset gcutil_COMMANDS
_gcutil_completer() {
    _completer "CLOUDSDK_COMPONENT_MANAGER_DISABLE_UPDATE_CHECK=1 gcutil help | grep -v '^information' | grep '^[a-z]' | sed -e 's/ .*//' -e '/^$/d'" gcutil
}

complete -o default -F _bq_completer bq
complete -o default -F _gsutil_completer gsutil
complete -o default -F _gcutil_completer gcutil
enemykite
  • 398
  • 1
  • 3
  • 8

8 Answers8

49

What worked for me was just using bass. Check it out: https://github.com/edc/bass

Just take the lines that gcloud adds to your bash_profile, and prepend bass to them in your .config/fish/config.fish file, as follows:

# The next line updates PATH for the Google Cloud SDK.
bass source '/Users/hunter/bin/google-cloud-sdk/path.bash.inc'

# The next line enables shell command completion for gcloud.
bass source '/Users/hunter/bin/google-cloud-sdk/completion.bash.inc'
Hunter Beast
  • 782
  • 7
  • 17
  • 3
    Thank you 100 times... Bass is awesome! – ivan Jul 11 '17 at 23:36
  • 2
    This doesn't appear to work anymore, or rather, I get files and folders for autocomplete when I hit tab. – Casey Jun 25 '18 at 18:25
  • 4
    https://github.com/Doctusoft/google-cloud-sdk-fish-completion doing that combined with `source '...../google-cloud-sdk/path.fish.inc'` worked for me. – Casey Jun 25 '18 at 18:29
  • I installed that repo and thought it was it, but in the end, I added `bass source ~/google-cloud-sdk/path.bash.inc` to `~/.config/fish/config.fish` to make it work for new terminals – lumaks Oct 23 '18 at 20:03
  • "bass!" in my language means "enough!". This was enough. +1 :) – Pratik Deoghare Jan 18 '19 at 15:37
17

As of today, I was able just to do

  1. brew install --cask google-cloud-sdk
  2. Added source /usr/local/Caskroom/google-cloud-sdk/latest/google-cloud-sdk/path.fish.inc to my ~/.config/fish/config.fish
  3. Clone https://github.com/aliz-ai/google-cloud-sdk-fish-completion then run install.sh.
David Xia
  • 5,075
  • 7
  • 35
  • 52
Rik
  • 790
  • 8
  • 11
5

For path.bash, all it does is add the Cloud SDK bin directory to your PATH. We put some weird stuff in there because we wanted it to work from inside the Cloud SDK directory even when behind, eg, a symlink. For your own system, just do the fsh equivalent of "export PATH=$PATH:/path/to/google-cloud-sdk/bin".

For the tab completion, I don't know how fsh's tab completion works, so I've got nothing.

John Asmuth
  • 1,052
  • 5
  • 7
3

I was able to set up completion by executing this:

# fisher v3
fisher add lgathy/google-cloud-sdk-fish-completion

# fisher v4
fisher install lgathy/google-cloud-sdk-fish-completion

Fisher can be found here: https://github.com/jorgebucaran/fisher

Completion source: https://github.com/lgathy/google-cloud-sdk-fish-completion

Elijah Lynn
  • 12,272
  • 10
  • 61
  • 91
mazorius
  • 31
  • 4
2

Fish support is now included out of the box with gcloud, however I ran into a pretty annoying issue. The code included in google-cloud-sdk/path.fish.inc (and @nafg's answer) leaves the directory changed, resulting in each new shell session starting in the google-cloud-sdk directory.

The modification I made was fairly simple, adding two extra lines to get the current working directory and restore it afterwards. This seems to have resolved the issue for me, so hopefully will help anyone else googling for "fish gcloud" problems.

set restore_dir (pwd -P)
set sdk_dir (builtin cd "$apparent_sdk_dir" > /dev/null; and pwd -P)
set bin_path "$sdk_dir/bin"
cd "$restore_dir"
Mensly
  • 81
  • 4
1

There's an interesting approach here: http://michelpm.com/blog/2013/07/26/switching-from-zsh-to-fish/

Basically it will run a bash script in bash, but it will diff how it changes the environment and apply that in fish.

However it won't work for completions and for your path.bash it's overkill. More like:

  • Change var=value to set var value
  • Change [ ... ] to test ...
  • Change $( ... ) to ( ... )
  • if doesn't need then and ends with end
  • Change || to ; or and && to ; and
  • Change export to set -x

So without testing here's what I would try:

set script_link ( readlink "$BASH_SOURCE" ); or set script_link $BASH_SOURCE
set apparent_sdk_dir ${script_link%/*}
if test "$apparent_sdk_dir" == "$script_link" ;
  set apparent_sdk_dir .
end
set sdk_dir ( command cd -P "$apparent_sdk_dir"; and pwd -P )
set bin_path $sdk_dir/bin
set -x PATH $bin_path:$PATH
nafg
  • 2,424
  • 27
  • 25
  • 1
    For path.bash I would edit your PATH the normal way, by adding the directory to the path directly. We added path.bash to make it easy for people who weren't familiar with dot-files, but a fsh user most likely is. – John Asmuth Oct 30 '14 at 15:13
1

using fisher:

fisher install lgathy/google-cloud-sdk-fish-completion

and you are good to go

Jorge Bucaran
  • 5,588
  • 2
  • 30
  • 48
Stav Alfi
  • 13,139
  • 23
  • 99
  • 171
  • Please [edit] your answer to include an explanation of how this works and why it is the solution to the problem described in the question. See [answer]. – Yunnosch Dec 10 '20 at 17:03
0

As of August 2023 the simplest and most straight-forward way to enable shell completions in fish is to edit ~/.config/fish/config.fish and add the following line:

. "/path/to/where/you/installed/google-cloud-sdk/path.fish.inc"

For example, if the google-cloud-sdk directory exists in /Users/foo/Applications then add:

. "/Users/foo/Applications/google-cloud-sdk/path.fish.inc"

Then restart fish.

anothermh
  • 9,815
  • 3
  • 33
  • 52