Update _beet to use zsh caching

Caching is now done with zsh builtin completion caching functions.
This commit is contained in:
vapniks 2018-05-01 21:58:11 +01:00 committed by GitHub
parent 965640859c
commit 209d281871
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -2,28 +2,29 @@
# zsh completion for beets music library manager and MusicBrainz tagger: http://beets.radbox.org/ # zsh completion for beets music library manager and MusicBrainz tagger: http://beets.radbox.org/
# NOTE: it will be very slow the first time you try to complete in a zsh shell (especially if you've enable many plugins) # Cache will be updated if it is older than the beets database or binary.
# You can make it faster in future by creating a cached version: # Need to set BEETS_LIBRARY to some preliminary value since it is used by the cache checking function.
# 1) perform a query completion with this file (_beet), e.g. do: beet list artist:"<TAB> typeset -g BEETS_LIBRARY=~/.config/beets/library.db
# to create the completion function (takes a few seconds) zstyle ":completion:${curcontext}:" cache-policy _beet_check_cache
# 2) save a copy of the completion function: which _beet > _beet_cached _beet_check_cache () {
# 3) save a copy of the query completion function: which _beet_query > _beet_query_cached [[ ! -a "${1}" ]] || [[ ! -a ${~BEETS_LIBRARY} ]] || [[ "${1}" -ot ${~BEETS_LIBRARY} ]] || [[ "${1}" -ot =beet ]]
# 4) copy the contents of _beet_query_cached to the top of _beet_cached }
# 5) copy and paste the _beet_field_values function from _beet to the top of _beet_cached # Try to retrieve the cache, and find out if it needs to be updated
# 6) add the following line to the top of _beet_cached: #compdef beet if ! _retrieve_cache beets || _cache_invalid beets; then
# 7) add the following line to the bottom of _beet_cached: _beet "$@" local updatecache=1
# 8) save _beet_cached to your completions directory (e.g. /usr/share/zsh/functions/Completion) # Location of database
# 9) add the following line to your .zshrc file: compdef _beet_cached beet typeset -g BEETS_LIBRARY="$(beet config|grep library|cut -f 2 -d ' ')"
# You will need to repeat this proceedure each time you enable new plugins if you want them to complete properly. # List of all fields
local -a fields
fields=(`beet fields | grep -G '^ ' | sort -u | colrm 1 2`)
fi
# useful: argument to _regex_arguments for matching any word # useful: argument to _regex_arguments for matching any word
local matchany=/$'[^\0]##\0'/ local matchany=/$'[^\0]##\0'/
# Deal with completions for querying and modifying fields.. # Deal with completions for querying and modifying fields..
local fieldargs matchquery matchmodify local fieldargs matchquery matchmodify
local -a fields
# get list of all fields
fields=(`beet fields | grep -G '^ ' | sort -u | colrm 1 2`)
# regexps for matching query and modify terms on the command line # regexps for matching query and modify terms on the command line
matchquery=/"(${(j/|/)fields[@]})"$':[^\0]##\0'/ matchquery=/"(${(j/|/)fields[@]})"$':[^\0]##\0'/
matchmodify=/"(${(j/|/)fields[@]})"$'(=[^\0]##|!)\0'/ matchmodify=/"(${(j/|/)fields[@]})"$'(=[^\0]##|!)\0'/
@ -43,14 +44,17 @@ function _join_lines() {
function _beet_field_values() function _beet_field_values()
{ {
local -a output fieldvals local -a output fieldvals
local library="$(beet config|grep library|cut -f 2 -d ' ')" local sqlcmd="select distinct $1 from items;"
output=$(sqlite3 ${~library} "select distinct $1 from items;")
case $1 case $1
in in
lyrics) lyrics)
fieldvals= fieldvals=
;; ;;
*) *)
if [[ "$(sqlite3 ${~BEETS_LIBRARY} ${sqlcmd} 2>&1)" =~ "no such column" ]]; then
sqlcmd="select distinct value from item_attributes where key=='$1' and value!='';"
fi
output="$(sqlite3 ${~BEETS_LIBRARY} ${sqlcmd} 2>/dev/null | sed -rn '/^-+$/,${{/^[- ]+$/n};p}')"
fieldvals=("${(f)output[@]}") fieldvals=("${(f)output[@]}")
;; ;;
esac esac
@ -68,8 +72,7 @@ queryelem="_values -S : 'query field (add an extra : to match by regexp)' '::' $
# store call to _values function for completing modify terms (no need to complete field values) # store call to _values function for completing modify terms (no need to complete field values)
modifyelem="_values -S = 'modify field (replace = with ! to remove field)' $(echo "'${^fields[@]}:: '")" modifyelem="_values -S = 'modify field (replace = with ! to remove field)' $(echo "'${^fields[@]}:: '")"
# Create completion function for queries # Create completion function for queries
_regex_arguments _beet_query "$matchany" \# \( "$matchquery" ":query:query string:$queryelem" \) \ _regex_arguments _beet_query "$matchany" \# \( "$matchquery" ":query:query string:$queryelem" \) \( "$matchquery" ":query:query string:$queryelem" \) \#
\( "$matchquery" ":query:query string:$queryelem" \) \#
# store regexps for completing lists of queries and modifications # store regexps for completing lists of queries and modifications
local -a query modify local -a query modify
query=( \( "$matchquery" ":query:query string:{_beet_query}" \) \( "$matchquery" ":query:query string:{_beet_query}" \) \# ) query=( \( "$matchquery" ":query:query string:{_beet_query}" \) \( "$matchquery" ":query:query string:{_beet_query}" \) \# )
@ -174,73 +177,76 @@ function _beet_subcmd_options()
} }
# Now build the arguments to _regex_arguments for each subcommand. # Now build the arguments to _regex_arguments for each subcommand.
local -a options regex_words_subcmds regex_words_help if [[ -n $updatecache ]]; then
local subcmd cmddesc local -a options regex_words_subcmds regex_words_help
for i in ${${(f)"$(beet help | _join_lines ' ' 3 'Commands:')"[@]}[@]} local subcmd cmddesc
do for i in ${${(f)"$(beet help | _join_lines ' ' 3 'Commands:')"[@]}[@]}
subcmd="${i[(w)1]}" do
# remove first word and parenthesised alias, replace : with -, [ with (, ] with ), and remove single quotes subcmd="${i[(w)1]}"
cmddesc="${${${${${i[(w)2,-1]##\(*\) #}//:/-}//\[/(}//\]/)}//\'/}" # remove first word and parenthesised alias, replace : with -, [ with (, ] with ), and remove single quotes
case $subcmd cmddesc="${${${${${i[(w)2,-1]##\(*\) #}//:/-}//\[/(}//\]/)}//\'/}"
case $subcmd
in in
(config) (config)
_regex_words options "config options" "$helpopt" "$pathopt" "$editopt" "$defaultopt" _regex_words options "config options" "$helpopt" "$pathopt" "$editopt" "$defaultopt"
options=("${reply[@]}") options=("${reply[@]}")
;; ;;
(import) (import)
_regex_words options "import options" "$helpopt" "$writeopt" "$nowriteopt" "$copyopt" "$nocopyopt"\ _regex_words options "import options" "$helpopt" "$writeopt" "$nowriteopt" "$copyopt" "$nocopyopt"\
"$inferopt" "$noinferopt" "$resumeopt" "$noresumeopt" "$nopromptopt" "$logopt" "$individualopt" "$confirmopt"\ "$inferopt" "$noinferopt" "$resumeopt" "$noresumeopt" "$nopromptopt" "$logopt" "$individualopt" "$confirmopt"\
"$retagopt" "$skipopt" "$noskipopt" "$flatopt" "$groupopt" "$retagopt" "$skipopt" "$noskipopt" "$flatopt" "$groupopt"
options=( "${reply[@]}" \# "${files[@]}" \# ) options=( "${reply[@]}" \# "${files[@]}" \# )
;; ;;
(list) (list)
_regex_words options "list options" "$helpopt" "$pathopt" "$albumopt" "$formatopt" _regex_words options "list options" "$helpopt" "$pathopt" "$albumopt" "$formatopt"
options=( "$reply[@]" \# "${query[@]}" ) options=( "$reply[@]" \# "${query[@]}" )
;; ;;
(modify) (modify)
_regex_words options "modify options" "$helpopt" "$dontmoveopt" "$writeopt" "$nowriteopt" "$albumopt" \ _regex_words options "modify options" "$helpopt" "$dontmoveopt" "$writeopt" "$nowriteopt" "$albumopt" \
"$noconfirmopt" "$formatopt" "$noconfirmopt" "$formatopt"
options=( "${reply[@]}" \# "${query[@]}" "${modify[@]}" ) options=( "${reply[@]}" \# "${query[@]}" "${modify[@]}" )
;; ;;
(move) (move)
_regex_words options "move options" "$helpopt" "$albumopt" "$destopt" "$copynomoveopt" _regex_words options "move options" "$helpopt" "$albumopt" "$destopt" "$copynomoveopt"
options=( "${reply[@]}" \# "${query[@]}") options=( "${reply[@]}" \# "${query[@]}")
;; ;;
(remove) (remove)
_regex_words options "remove options" "$helpopt" "$albumopt" "$removeopt" _regex_words options "remove options" "$helpopt" "$albumopt" "$removeopt"
options=( "${reply[@]}" \# "${query[@]}" ) options=( "${reply[@]}" \# "${query[@]}" )
;; ;;
(stats) (stats)
_regex_words options "stats options" "$helpopt" "$exactopt" _regex_words options "stats options" "$helpopt" "$exactopt"
options=( "${reply[@]}" \# "${query[@]}" ) options=( "${reply[@]}" \# "${query[@]}" )
;; ;;
(update) (update)
_regex_words options "update options" "$helpopt" "$albumopt" "$dontmoveopt" "$pretendopt" "$formatopt" _regex_words options "update options" "$helpopt" "$albumopt" "$dontmoveopt" "$pretendopt" "$formatopt"
options=( "${reply[@]}" \# "${query[@]}" ) options=( "${reply[@]}" \# "${query[@]}" )
;; ;;
(write) (write)
_regex_words options "write options" "$helpopt" "$pretendopt" _regex_words options "write options" "$helpopt" "$pretendopt"
options=( "${reply[@]}" \# "${query[@]}" ) options=( "${reply[@]}" \# "${query[@]}" )
;; ;;
(fields|migrate|version) (fields|migrate|version)
options=() options=()
;; ;;
(help) (help)
# The help subcommand is treated separately # The help subcommand is treated separately
continue continue
;; ;;
(*) # completions for plugin commands are generated using _beet_subcmd_options (*) # completions for plugin commands are generated using _beet_subcmd_options
_beet_subcmd_options "$subcmd" _beet_subcmd_options "$subcmd"
options=( \( "${reply[@]}" \# "${query[@]}" \) ) options=( \( "${reply[@]}" \# "${query[@]}" \) )
;; ;;
esac esac
# Create variable for holding option for this subcommand, and assign to it (needs to have a unique name). # Create variable for holding option for this subcommand, and assign to it (needs to have a unique name).
typeset -a opts_for_$subcmd typeset -a opts_for_$subcmd
set -A opts_for_$subcmd ${options[@]} # Assignment MUST be done using set (other methods fail). set -A opts_for_$subcmd ${options[@]} # Assignment MUST be done using set (other methods fail).
regex_words_subcmds+=("$subcmd:$cmddesc:\${(@)opts_for_$subcmd}") regex_words_subcmds+=("$subcmd:$cmddesc:\${(@)opts_for_$subcmd}")
# Add to regex_words args for help subcommand # Add to regex_words args for help subcommand
regex_words_help+=("$subcmd:$cmddesc") regex_words_help+=("$subcmd:$cmddesc")
done done
_store_cache beets regex_words_subcmds regex_words_help BEETS_LIBRARY fields
fi
local -a opts_for_help local -a opts_for_help
_regex_words subcmds "subcommands" "${regex_words_help[@]}" _regex_words subcmds "subcommands" "${regex_words_help[@]}"
@ -253,7 +259,7 @@ _regex_words options "global options" "$configopt" "$debugopt" "$libopt" "$helpo
globalopts=("${reply[@]}") globalopts=("${reply[@]}")
# Create main completion function # Create main completion function
#local -a subcmds local -a subcmds
_regex_words subcmds "subcommands" "${regex_words_subcmds[@]}" _regex_words subcmds "subcommands" "${regex_words_subcmds[@]}"
subcmds=("${reply[@]}") subcmds=("${reply[@]}")
_regex_arguments _beet "$matchany" \( "${globalopts[@]}" \# \) "${subcmds[@]}" _regex_arguments _beet "$matchany" \( "${globalopts[@]}" \# \) "${subcmds[@]}"
@ -267,3 +273,4 @@ _beet "$@"
# Local Variables: # Local Variables:
# mode:shell-script # mode:shell-script
# End: # End: