mirror of https://github.com/mattmc3/antidote
124 lines
4.1 KiB
Bash
124 lines
4.1 KiB
Bash
#!/bin/zsh
|
|
|
|
### Parse antidote's bundle DSL to an associative array.
|
|
# Example:
|
|
# __antidote_parser 'foo/bar path:plugins/baz kind:fpath pre:myprecmd # comment'
|
|
# typeset -A bundle=( [kind]=fpath [path]=plugins/baz [pre]=myprecmd [name]=foo/bar )
|
|
#
|
|
# Notes:
|
|
# bundle_str : antidote DSL syntax
|
|
# bundle : assoc array representation
|
|
# bundle_repr : Zsh serialization of the bundle assoc arrary
|
|
#
|
|
# Metadata:
|
|
# _repodir : The clone destination dir
|
|
# _type : The type of bundle (url, repo, path, ?)
|
|
# _repo : The user/repo short form of the URL
|
|
# _url : The git repo URL
|
|
#
|
|
#function __antidote_parser {
|
|
emulate -L zsh; setopt local_options $_adote_funcopts
|
|
local MATCH MBEGIN MEND; local -a match mbegin mend # appease 'warn_create_global'
|
|
local bundle_str bundle_var bundle_repr gitsite str pair key value
|
|
local -a kvpairs parts
|
|
local -A bundle
|
|
|
|
bundle_str="$1"
|
|
bundle_var="${2:-bundle}"
|
|
|
|
# Allow the user to override the default git site if they really want to
|
|
zstyle -s ':antidote:gitremote' url 'gitsite' \
|
|
|| gitsite='https://github.com'
|
|
gitsite="${gitsite%/}"
|
|
|
|
# Remove anything after the first '#'
|
|
bundle_str=${bundle_str%%\#*}
|
|
# Trim spaces
|
|
bundle_str=${${bundle_str/#[[:space:]]#}/%[[:space:]]#}
|
|
# Skip empty bundle strings
|
|
[[ -z "$bundle_str" ]] && return 0
|
|
# 1st field gets a 'name:' prefix so we can treat everything as key:val pairs
|
|
bundle_str="name:${bundle_str}"
|
|
|
|
# Split line into key-value pairs with quoting
|
|
kvpairs=(${(Q)${(z)bundle_str}})
|
|
for pair in "${kvpairs[@]}"; do
|
|
key=${pair%%:*} # Extract key (before first ':')
|
|
if [[ "$pair" == *:* ]]; then
|
|
value=${pair#*:} # Extract value (after first ':')
|
|
else
|
|
value=
|
|
fi
|
|
bundle[$key]=$value
|
|
done
|
|
|
|
# Enhance the bundle with metadata fields. Metadata fields begin with an underscore
|
|
# since those will never be part of the DSL. Let's start with _type, which tells us
|
|
# whether the bundle is a URL, a user/repo, or a path
|
|
if [[ "$bundle[name]" == *://*/*/* || "$bundle[name]" == (ssh|git)@*:*/* ]]; then
|
|
if [[ "$bundle[name]" == *://*/*/*/* || "$bundle[name]" == *@*:*/*/* ]]; then
|
|
bundle[_type]="?"
|
|
else
|
|
bundle[_type]="url"
|
|
fi
|
|
elif [[ "$bundle[name]" == *('@'|':')* ]] ; then
|
|
bundle[_type]="?" # bad URLs
|
|
elif [[ "$bundle[name]" == ('~'|'$'|'.')* ]]; then
|
|
bundle[_type]="path"
|
|
elif [[ "$bundle[name]" == */* && "$bundle[name]" != */*/* ]]; then
|
|
bundle[_type]="repo"
|
|
elif [[ "$bundle[name]" == */* ]]; then
|
|
bundle[_type]="path"
|
|
else
|
|
bundle[_type]="?"
|
|
fi
|
|
|
|
# For git repos, we add a metadata field for the URL
|
|
if [[ "$bundle[_type]" == url ]]; then
|
|
str="$bundle[name]"
|
|
str=${str%.git}
|
|
str=${str:gs/\:/\/}
|
|
parts=( ${(ps./.)str} )
|
|
if [[ $#parts -gt 1 ]]; then
|
|
bundle[_repo]="${parts[-2]}/${parts[-1]}"
|
|
else
|
|
bundle[_repo]="$str"
|
|
fi
|
|
bundle[_url]="$bundle[name]"
|
|
elif [[ "$bundle[_type]" == repo ]]; then
|
|
bundle[_repo]="${bundle[name]}"
|
|
bundle[_url]="${gitsite}/${bundle[name]}"
|
|
fi
|
|
|
|
# If there's a git URL, we also need to set the _repodir
|
|
if [[ -v bundle[_url] ]]; then
|
|
# TODO: Remove for antidote 2.0
|
|
if zstyle -t ':antidote:compatibility-mode' 'antibody' || ! zstyle -t ':antidote:bundle' use-friendly-names; then
|
|
# sanitize URL for safe use as a dir name
|
|
# ex: $ANTIDOTE_HOME/https-COLON--SLASH--SLASH-github.com-SLASH-zsh-users-SLASH-zsh-autosuggestions
|
|
str="$bundle[_url]"
|
|
str=${str%.git}
|
|
str=${str:gs/\@/-AT-}
|
|
str=${str:gs/\:/-COLON-}
|
|
str=${str:gs/\//-SLASH-}
|
|
bundle[_repodir]="$str"
|
|
else
|
|
bundle[_repodir]="$bundle[_repo]"
|
|
fi
|
|
fi
|
|
|
|
# Print the parsed bundle assoc arr using whatever bundle_var the user wants
|
|
bundle_repr="$(declare -p bundle)"
|
|
bundle_repr="typeset -A ${bundle_var}=${bundle_repr#*=}"
|
|
|
|
# Sanity check that I probably don't need.
|
|
if [[ ! "$bundle_repr" =~ "^typeset\ -A\ ${bundle_var}=" ]]; then
|
|
print -ru2 -- "antidote: Unable to parse bundle string: '$bundle_str'."
|
|
return 1
|
|
fi
|
|
|
|
# Return/print the result.
|
|
typeset -g REPLY="$bundle_repr"
|
|
print -r -- "$REPLY"
|
|
#}
|