Open ghost opened 8 years ago
I'll have to have a look at this. Completion was quite tricky under Zsh but Zsh completion is pretty sophisticated compared to Bash. I'll see how easy it is to add this. On 23 Jun 2016 16:53, "fturco" notifications@github.com wrote:
It would be cool to have tab completion for bash too.
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/oniony/TMSU/issues/78, or mute the thread https://github.com/notifications/unsubscribe/AAAXB0HLW2II3dP5JwnHl5wTGpCk3n9Iks5qOqwOgaJpZM4I89lm .
I've written this a few months ago. It's a very rudimentary bash completion -- all it supports is completing tag names and values for tmsu tag
. It doesn't handle values with spaces and none of the other subcommands.
Might be a usable stopgap for people.
# This belongs to /etc/bash_completion.d/tmsu
# TODO: handle spaces in values.
have tmsu &&
_tmsu()
{
local cur prev
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
prev=${COMP_WORDS[COMP_CWORD-1]}
prev_prev=${COMP_WORDS[COMP_CWORD-2]}
if [ "$COMP_CWORD" -eq 1 ]; then
COMPREPLY=( $(compgen -W "config copy delete dupes files help imply init merge mount rename repair stats status tag tags unmount untag untagged values version vfs" -- ${cur}) );
return 0
elif [ "$COMP_CWORD" = "2" ]; then
_filedir
return 0
else
case "${COMP_WORDS[1]}" in
tag)
if [ "$cur" = "=" ]; then
COMPREPLY=( $(compgen -W "$(tmsu values ${prev} 2> /dev/null)" -- "") )
elif [ "$prev" = "=" ]; then
COMPREPLY=( $(compgen -W "$(tmsu values ${prev_prev})" -- $cur) )
else
COMPREPLY=( $(compgen -W "$(tags)" -- $cur) )
fi
return 0
;;
esac
fi
}
function tags()
{
# Select all tag/value pairs for the completion.
# NOTE: there is no tag/value association without it being applied to a file.
# So some values don't show up because there's no file for them yet (or anymore).
local TAG_VALUE_QUERY='SELECT DISTINCT tag.name || "=" || value.name FROM file_tag JOIN tag ON tag_id=tag.id JOIN value ON value_id=value.id;';
echo $(sqlite3 "$HOME/.tmsu/default.db" "$TAG_VALUE_QUERY")
# Select the remaining tags (i.e. all tags without any value associated with them)
# (we don't want to offer a "value tag" again in its empty form)
local STANDALONE_TAGS='SELECT DISTINCT name FROM tag LEFT OUTER JOIN file_tag ON tag_id=id WHERE (value_id IS NULL) OR (value_id IS 0);'
echo $(sqlite3 "$HOME/.tmsu/default.db" "$STANDALONE_TAGS")
};
complete -F _tmsu tmsu
Hi,
I completed the bash_completion script to handle help command, complete with tags and filenames.
This way you can type: tmsu tag myfile.pdf
<TAB>
to have the first tag, then <TAB>
again to complete a second one, etc.
There are still work to do to support the completion of options like --tags=
tmsu tag --tags="landscape" field1.jpg field2.jpg
# This belongs to /etc/bash_completion.d/tmsu or ~/.bash_completion
# Original from tomassedovic (https://github.com/oniony/TMSU/issues/78)
# TODO: handle spaces in values.
have tmsu &&
_tmsu()
{
local cur prev
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
prev=${COMP_WORDS[COMP_CWORD-1]}
prev_prev=${COMP_WORDS[COMP_CWORD-2]}
if [ "$COMP_CWORD" -eq 1 ]; then
COMPREPLY=( $(compgen -W "config copy delete dupes files help imply init merge mount rename repair stats status tag tags unmount untag untagged values version vfs" -- ${cur}) );
return 0
else
case "${COMP_WORDS[1]}" in
tag|files|untag)
local IFS=$'\n'
if [ "$cur" = "=" ]; then
# Complete values for a tag (ex: year=), so no need for filenames
COMPREPLY=( $(compgen -W "$(tmsu values ${prev} 2> /dev/null)" -- "") )
elif [ "$prev" = "=" ]; then
# If previous "word" is symbol "=", used only when the "=" is not escaped
COMPREPLY=( $(compgen -f -W "$(tmsu values ${prev_prev})" -- $cur) )
else
# NORMAL case: let's print the tags, then filenames with the separator between.
# The if is used to show only the separator if there are filenames
COMPREPLY=( $(compgen -W "$(tags)" -- $cur) $( if [ "" != "$(compgen -f -- $cur)" ]; then echo "##########__Fichiers__##########"; fi) $(compgen -f -- $cur))
fi
return 0
;;
help)
COMPREPLY=( $(compgen -W "config copy delete dupes files help imply init merge mount rename repair stats status tag tags unmount untag untagged values version vfs" -- ${cur}) );
return 0
;;
*)
_filedir
return 0
;;
esac
fi
}
function tags()
{
DB=$(tmsu info 2>&1 | sed -n -e "/Database/{s/Database: //;p}")
if [ -e "${DB}" ]; then
# Select all tag/value pairs for the completion.
# NOTE: there is no tag/value association without it being applied to a file.
# So some values don't show up because there's no file for them yet (or anymore).
local TAG_VALUE_QUERY='SELECT DISTINCT tag.name || "=" || value.name FROM file_tag JOIN tag ON tag_id=tag.id JOIN value ON value_id=value.id order by tag.name;';
sqlite3 "${DB}" "$TAG_VALUE_QUERY"
# Select the remaining tags (i.e. all tags without any value associated with them)
# (we don't want to offer a "value tag" again in its empty form)
local STANDALONE_TAGS='SELECT DISTINCT name FROM tag LEFT OUTER JOIN file_tag ON tag_id=id WHERE (value_id IS NULL) OR (value_id IS 0) order by name;'
sqlite3 "${DB}" "$STANDALONE_TAGS"
fi;
};
# Use of option "nosort" because it is handled in the SQL requests and permits to show the filenames at the end
complete -o nosort -F _tmsu tmsu
Well, I wrote a custom modification for completion with fzf. People who came here searching for related things, have a look https://github.com/kvngvikram/custom_tmsu#custom_tmsu
Nice @kvngvikram, @tomassedovic and @Master-jim , these two scripts work very well together :) Basically I moved /usr/bin/tmsu to /usr/bin/tmsu_original and put the custom one in /usr/bin/tmsu Now I get tab completion, AND the nice fzf popup tag finder.
I made a small adjustment to not show the file list if using the "files" command (which doesn't take file names). (and stored the tmsu main command for reuse).
And also added an option to summarize or display the values like so (which required adding = to the COMP_WORDBREAKS
variable, which fixed what I think was a bug in the matching it in your script), because I have hundreds of values in some of my value tags). Configured like so
# Use this to control if values are displayed or just summarized, they will be expanded after the = is typed/selected
#VALUES="display"
VALUES="summarize"
COMP_WORDBREAKS="${COMP_WORDBREAKS}="
$ tmsu files <tab>
for= 5 values
star= 151 values
studio= 17 values
BEST
...
$ tmsu files for
for= 5 values foreign_language
$ tmsu files for=
cat claudia joe meow sharni
And also implemented tab completion on the values command
$ tmsu values <tab>
for star studio
$ tmsu values for<enter>
cat claudia joe meow sharni
# This belongs to /etc/bash_completion.d/tmsu or ~/.bash_completion
# Original from tomassedovic (https://github.com/oniony/TMSU/issues/78)
# TODO: handle spaces in values.
# Use this to control if values are displayed or just summarized, they will be expanded after the = is typed/selected
#VALUES="display"
VALUES="summarize"
COMP_WORDBREAKS="${COMP_WORDBREAKS}="
have tmsu &&
_tmsu()
{
local cur prev prev_prev tmsu_command
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
prev=${COMP_WORDS[COMP_CWORD-1]}
prev_prev=${COMP_WORDS[COMP_CWORD-2]}
tmsu_command="${COMP_WORDS[1]}"
if [ "$COMP_CWORD" -eq 1 ]; then
COMPREPLY=( $(compgen -W "config copy delete dupes files help imply init merge mount rename repair stats status tag tags unmount untag untagged values version vfs" -- ${cur}) );
return 0
else
case "${tmsu_command}" in
tag|files|untag)
local IFS=$'\n'
if [ "$cur" = "=" ]; then
# Complete values for a tag (ex: year=), so no need for filenames
COMPREPLY=( $(compgen -W "$(tmsu values ${prev} 2> /dev/null)" -- "") )
elif [ "$prev" = "=" ]; then
# If previous "word" is symbol "=", used only when the "=" is not escaped
COMPREPLY=( $(compgen -f -W "$(tmsu values ${prev_prev})" -- $cur) )
else
# NORMAL case: let's print the tags, then filenames with the separator between.
# The if is used to show only the separator if there are filenames
if [[ ${tmsu_command} == files ]]; then # Don't show filenames for the files command (which only takes tags)
COMPREPLY=( $(compgen -W "$(tags)" -- $cur))
else
COMPREPLY=( $(compgen -W "$(tags)" -- $cur) $( if [ "" != "$(compgen -f -- $cur)" ]; then echo "##########__FILES__##########"; fi) $(compgen -f -- $cur))
fi
fi
return 0
;;
values)
COMPREPLY=( $(compgen -W "$(tags | grep '=' | cut -f1 -d'=')" -- $cur))
return 0
;;
help)
COMPREPLY=( $(compgen -W "config copy delete dupes files help imply init merge mount rename repair stats status tag tags unmount untag untagged values version vfs" -- ${cur}) );
return 0
;;
*)
_filedir
return 0
;;
esac
fi
}
function tags()
{
DB=$(tmsu info 2>&1 | sed -n -e "/Database/{s/Database: //;p}")
if [ -e "${DB}" ]; then
# Select all tag/value pairs for the completion.
# NOTE: there is no tag/value association without it being applied to a file.
# So some values don't show up because there's no file for them yet (or anymore).
if [[ $VALUES == summarize ]]; then
local TAG_VALUE_QUERY='SELECT tag.name || "= " || count(distinct value.name) || " values" FROM file_tag JOIN tag ON tag_id=tag.id JOIN value ON value_id=value.id group by tag.name order by tag.name;';
else
local TAG_VALUE_QUERY='SELECT DISTINCT tag.name || "=" || value.name FROM file_tag JOIN tag ON tag_id=tag.id JOIN value ON value_id=value.id order by tag.name;';
fi
sqlite3 "${DB}" "$TAG_VALUE_QUERY"
# Select the remaining tags (i.e. all tags without any value associated with them)
# (we don't want to offer a "value tag" again in its empty form)
local STANDALONE_TAGS='SELECT DISTINCT name FROM tag LEFT OUTER JOIN file_tag ON tag_id=id WHERE (value_id IS NULL) OR (value_id IS 0) order by name;'
sqlite3 "${DB}" "$STANDALONE_TAGS"
fi;
};
# Use of option "nosort" because it is handled in the SQL requests and permits to show the filenames at the end
complete -o nosort -F _tmsu tmsu
I've saved this to a gist if anyone wants to improve or fork it. https://gist.github.com/shanness/a4855a397ed6568b946f46fbc6fdbb09
It would be cool to have tab completion for bash too.