setup update complete
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
#####################################################################
|
||||
|
||||
setup.filesystem.write-managed-block() {
|
||||
# replaces (or appends) a dotwryn-managed block in a file, taking the
|
||||
# block body from stdin, so that every run refreshes the block rather
|
||||
# than appending another copy of it
|
||||
#
|
||||
# callers should use a "<<-" heredoc: it strips leading TABS (letting
|
||||
# the body stay indented with its caller) but leaves SPACES alone, so
|
||||
# indent the block's own nesting with spaces to keep it in the output
|
||||
#
|
||||
# "--one-line" trades the begin/end banner for a trailing comment on
|
||||
# the line itself, which suits a one-line entry like an rc source
|
||||
local file tag
|
||||
local comment='#'
|
||||
local one_line=false
|
||||
|
||||
local _s _p
|
||||
while [[ "${#}" -gt 0 ]]
|
||||
do
|
||||
_s=1
|
||||
case "${1}" in
|
||||
( --comment ) _s=2
|
||||
comment="${2}"
|
||||
;;
|
||||
( --tag ) _s=2
|
||||
tag="${2}"
|
||||
;;
|
||||
( --one-line )
|
||||
one_line=true
|
||||
;;
|
||||
( * )
|
||||
case "$((_p+=1))" in
|
||||
( 1 ) file="${1}" ;;
|
||||
( * ) echo.error "write-managed-block: unexpected argument '${1}'" ;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
shift "${_s}"
|
||||
done
|
||||
unset _s _p
|
||||
|
||||
[[ "${file}" ]] \
|
||||
|| echo.error 'write-managed-block: no file given' \
|
||||
|| return 1
|
||||
|
||||
# a single file can carry several managed blocks, so each one has to be
|
||||
# named to know which of them it owns
|
||||
[[ "${tag}" ]] \
|
||||
|| echo.error "write-managed-block: no --tag given for '${file}'" \
|
||||
|| return 1
|
||||
|
||||
local body="$(cat)"
|
||||
|
||||
[[ "${one_line}" == false ]] || [[ "${body}" != *$'\n'* ]] \
|
||||
|| echo.error "write-managed-block: --one-line needs a single-line body for '${file}'" \
|
||||
|| return 1
|
||||
|
||||
mkdir -p -- "${file:h}"
|
||||
touch -- "${file}"
|
||||
|
||||
local -a lines block
|
||||
lines=("${(@f)$(<"${file}")}")
|
||||
[[ -s "${file}" ]] || lines=()
|
||||
|
||||
# an existing block is replaced where it sits, so anything the user
|
||||
# wrote around it keeps its position
|
||||
local begin_index end_index
|
||||
case "${one_line}" in
|
||||
( true )
|
||||
local marker="${comment} managed by dotwryn setup (${tag})"
|
||||
block=("${body} ${marker}")
|
||||
|
||||
# "(b)" keeps the tag's parentheses literal rather than glob
|
||||
begin_index="${lines[(i)*${(b)marker}]}"
|
||||
end_index="${begin_index}"
|
||||
;;
|
||||
( false )
|
||||
local begin="${comment} >>> managed by dotwryn setup (${tag}) >>>"
|
||||
local end="${comment} <<< managed by dotwryn setup (${tag}) <<<"
|
||||
block=("${begin}" "${(@f)body}" "${end}")
|
||||
|
||||
begin_index="${lines[(ie)${begin}]}"
|
||||
end_index="${lines[(ie)${end}]}"
|
||||
[[ "${end_index}" -le "${#lines[@]}" ]] || end_index="${#lines[@]}"
|
||||
;;
|
||||
esac
|
||||
|
||||
if [[ "${begin_index}" -gt "${#lines[@]}" ]]
|
||||
then
|
||||
lines+=("${block[@]}")
|
||||
else
|
||||
lines=(
|
||||
"${lines[@]:0:$((begin_index - 1))}"
|
||||
"${block[@]}"
|
||||
"${lines[@]:${end_index}}"
|
||||
)
|
||||
fi
|
||||
|
||||
print -l -- "${lines[@]}" > "${file}"
|
||||
}
|
||||
Reference in New Issue
Block a user