diff options
author | Ondrej Holy <oholy@redhat.com> | 2018-06-15 11:20:51 +0200 |
---|---|---|
committer | Ondrej Holy <oholy@redhat.com> | 2018-06-15 12:34:10 +0200 |
commit | e0e0f259c309ad910d6db7cd4ff60ac23127cd2d (patch) | |
tree | 716b80004363c91e2b93c55dc1ae810743c7c407 | |
parent | 45f9b5a33619c28c1eb572f3739e7628554ba46c (diff) | |
download | glib-wip/oholy/gio-bash-completion.tar.gz |
gio: Add bash completion for gio toolwip/oholy/gio-bash-completion
GVfs utils used to have bash completion, which was pretty useful. However,
it hasn't been ported to gio tool unfortunately. GLib provides completion
for various utils already, so it would be nice to provide completion also
for gio tool. I've updated old bash completion code and merged with some
my old unmerged fixes.
The gvfs completion used "gvfs-ls --show-completions" helper. This mentioned
option hasn't been obviously ported to "gio list" and the proposed completion
doesn't add this option in "gio list" to not pollute the codes, but maybe it
is a bit slower as consequence.
The proposed bash completion suggests subcommands, uris and paths including
the remote mounts. It contains some workarounds, especially because of proper
handling of paths with colons and other special chars (like spaces)...
-rw-r--r-- | gio/Makefile.am | 1 | ||||
-rw-r--r-- | gio/completion/.gitignore | 1 | ||||
-rwxr-xr-x | gio/completion/gio | 120 | ||||
-rw-r--r-- | gio/meson.build | 1 |
4 files changed, 123 insertions, 0 deletions
diff --git a/gio/Makefile.am b/gio/Makefile.am index 7c7f247c0..8a70bf98c 100644 --- a/gio/Makefile.am +++ b/gio/Makefile.am @@ -927,6 +927,7 @@ completiondir = $(datadir)/bash-completion/completions completion_DATA = \ completion/gapplication \ completion/gdbus \ + completion/gio \ completion/gsettings \ completion/gresource EXTRA_DIST += $(completion_DATA) diff --git a/gio/completion/.gitignore b/gio/completion/.gitignore new file mode 100644 index 000000000..6930af958 --- /dev/null +++ b/gio/completion/.gitignore @@ -0,0 +1 @@ +!gio diff --git a/gio/completion/gio b/gio/completion/gio new file mode 100755 index 000000000..c1db98561 --- /dev/null +++ b/gio/completion/gio @@ -0,0 +1,120 @@ +# +# Copyright (C) 2018 Red Hat, Inc. +# +# This library is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 of the +# licence, or (at your option) any later version. +# +# This is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +# License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library; if not, see <http://www.gnu.org/licenses/>. +# + +# Check for bash +[ -z "$BASH_VERSION" ] && return + +#################################################################################################### + +# Check whether the suggestions have common prefix (i.e. suggestions won't be +# shown and prefix will be completed first) +__has_common_prefix() { + for (( i = 1; i < ${#COMPREPLY[@]}; i++ )); do + if [[ "${COMPREPLY[i-1]:${#cur}:1}" != "${COMPREPLY[i]:${#cur}:1}" ]]; then + return 1 # False + fi + done + + return 0 # True +} + +# Complete file location +__gio_location() { + # Prevent breaking on colons, we have to work with uris + local cur + _get_comp_words_by_ref -n : cur + + # Resolve dirname for dir listing + local dir="" + if [[ $cur =~ "/"$ ]]; then + dir="$cur" + elif [[ $cur =~ "/" ]]; then + dir="$(dirname "$cur")/" + fi + + # List daemon mounts, just if dir is not specified, or looks like scheme + local mounts=() + if [[ $dir == "" ]] || [[ $dir =~ ":"$ && ! $dir =~ "/" ]]; then + while IFS=$'\n' read mount; do + # Do not care about local mounts + [[ "$mount" =~ ^"file:" ]] && continue + + # Use only matching mounts + [[ "$mount" =~ ^"$cur" && "$mount" != "$cur" ]] && mounts+=("$mount") + done < <(gio mount -l | sed -n -r 's/^ *Mount\([0-9]+\): .* -> (.*)$/\1/p') + fi + + # Workaround to unescape dir name (e.g. "\ " -> " ") + declare -a tmp="( ${dir} )" + unescaped_dir="${tmp[0]}" + + # List files + local files=() + local names=() + while IFS=$'\t' read name size type; do + # Escape name properly + local escaped_name="$(printf "%q" "$name")" + + # Append slash for directories and space for files + if [[ "$type" == "(directory)" ]]; then + escaped_name="$escaped_name/" + else + escaped_name="$escaped_name " + fi + + path="$dir$escaped_name" + + # Use only matching paths + if [[ "$path" =~ ^"$cur" ]]; then + files+=("$path") + names+=("$escaped_name") + fi + done < <(gio list -hl "$unescaped_dir" 2> /dev/null) + + COMPREPLY=("${files[@]}" "${mounts[@]}") + + # Workaround to show suggestions as basenames only + if ! __has_common_prefix; then + COMPREPLY=("${mounts[@]} ${names[@]}") + + # Workaround to prevent overwritting suggestions, it adds empty + # suggestion, otherwise names with colons will be corrupted + COMPREPLY+=(" ") + + return 0 + fi + + # Workaround to complete names with colons, it removes colon prefix from + # COMPREPLY + __ltrim_colon_completions "$cur" +} + +__gio() { + # Complete subcommands + if (( ${COMP_CWORD} == 1 )); then + COMPREPLY=($(compgen -W "help version cat copy info list mime mkdir monitor mount move open rename save set trash tree" -- "${COMP_WORDS[1]}")) + compopt +o nospace + return 0 + fi + + # Complete file locations + __gio_location +} + +#################################################################################################### + +complete -o nospace -F __gio gio diff --git a/gio/meson.build b/gio/meson.build index 9544ab395..f37911fac 100644 --- a/gio/meson.build +++ b/gio/meson.build @@ -757,6 +757,7 @@ if have_bash install_data([ 'completion/gapplication', 'completion/gdbus', + 'completion/gio', 'completion/gsettings', 'completion/gresource' ], |