Files
dotfiles/private_dot_local/share/elfos/common/block_in_file.sh

196 lines
5.6 KiB
Bash

function __block_in_file__help() {
local func="$1"
if [[ "$func" = "update" ]]
then
echo "block_in_file [<OPTIONS>] <FILE> <ID> <BLOCK>"
else
echo "block_in_file_remove [<OPTIONS>] <FILE> <ID>"
fi
echo "$func [<OPTIONS>] <FILE> <ID> <BLOCK>"
echo
echo "OPTIONS:"
if [[ "$func" = "update" ]]
then
echo " --before <MATCH> insert block before matched line"
echo " --after <MATCH> insert block after matched line"
fi
echo " --id-start-pre <str> set id-start-pre to str"
echo " --id-start-post <str> set id-start-post to str"
echo " --id-end-pre <str> set id-end-pre to str"
echo " --id-end-post <str> set id-end-post to str"
echo
echo "ID:"
echo " an identifier string to regonise the block."
if [[ "$func" = "update" ]]
then
echo
echo "MATCH:"
echo " line search/match string in grep format"
fi
echo
echo "block fomat:"
echo " <id-start-pre><id><id-start-post>"
echo " <block>"
echo " <id-end-pre><id><id-end-post>"
}
function block_in_file() {
__block_in_file__inner "update" $*
}
function block_in_file_remove() {
__block_in_file__inner "remove" $*
}
function __block_in_file__inner() {
local FN="$1"
local BEFORE="EOF"
local AFTER="SOF"
local ID_START_PRE="#START manged by elf_packages: "
local ID_START_POST=""
local ID_END_PRE="#END "
local ID_END_POST=""
while [[ $1 == \-* ]]
do
case "$1" in
"--before")
if [[ "$FN" = "update" ]]
then
shift
BEFORE="$1"
shift
else
echo "ERROR: invalid options $1"
__block_in_file__help "$FN"
exit 1
fi
;;
"--after")
if [[ "$FN" = "update" ]]
then
shift
AFTER="$1"
shift
else
echo "ERROR: invalid options $1"
__block_in_file__help "$FN"
exit 1
fi
;;
"--id-start-pre")
shift
ID_START_PRE="$1"
shift
;;
"--id-start-post")
shift
ID_START_POST="$1"
shift
;;
"--id-end-pre")
shift
ID_END_PRE="$1"
shift
;;
"--id-end-post")
shift
ID_END_POST="$1"
shift
;;
"--")
shift
break
;;
*)
echo "ERROR: invalid options $1"
__block_in_file__help "$FN"
exit 1
;;
esac
done
local FILE="$1"
local ID="$2"
local BLOCK="$3"
if [[ ! -f "$FILE" ]]
then
echo "ERROR: file not found: $FILE"
exit 1
fi
local id_start_line="${ID_START_PRE}${ID}${ID_START_POST}"
local id_end_line="${ID_END_PRE}${ID}${ID_END_POST}"
if [[ "$func" = "update" ]]
then
block_in_file "$FILE" "$id_start_line" "$id_end_line" "$BEFORE" "$AFTER" "$BLOCK"
else
block_in_file_remove "$FILE" "$id_start_line" "$id_end_line" "$BLOCK"
fi
}
function __block_in_file__inner_update() {
local file="$1"
local id_start_line="$2"
local id_end_line="$3"
local before="$4"
local after="$5"
local block="$6"
if [[ -z "$(grep "^$id_start_line\$" "$file")" ]]
then
# no existing block. add a new one
if [ "$before" == "EOF" ]
then
before="$(($(cat "$file" | wc --lines) + 1))"
else
before="$(grep --line-number -e "$before" "$file" | head --lines=1 | awk -F: '{{print $1}}')"
fi
if [ "$after" == "SOF" ]
then
after="0"
else
after="$(grep --line-number -e "$after" "$file" | head --lines=1 | awk -F: '{{print $1}}')"
fi
if [[ $after > $before ]]; then
echo "ERROR: after is bigger than before, no place to put the block"
exit 1
fi
tmp_file=$(mktemp)
head --lines=$AFTER "$file" >"$tmp_file"
echo "$id_start_line" >>"$tmp_file"
echo "$block" >>"$tmp_file"
echo "$id_end_line" >>"$tmp_file"
tail --lines=+$(($AFTER + 1)) "$file" >>"$tmp_file"
mv "$tmp_file" "$file"
else
# update existing block
local start="$(grep --line-number -e "^$id_start_line\$" "$file" | head --lines=1 | awk -F: '{{print $1}}')"
local end="$(grep --line-number -e "^$id_end_line\$" "$file" | head --lines=1 | awk -F: '{{print $1}}')"
local tmp_file=$(mktemp)
head --lines=$start "$file" >"$tmp_file"
echo "$block" >>"$tmp_file"
tail --lines=+$end "$file" >>"$tmp_file"
mv "$tmp_file" "$file"
fi
}
function __block_in_file__inner_remove() {
local file="$1"
local id_start_line="$2"
local id_end_line="$3"
local block="$4"
local start="$(grep --line-number -e "^$id_start_line\$" "$file" | head --lines=1 | awk -F: '{{print $1}}')"
local end="$(grep --line-number -e "^$id_end_line\$" "$file" | head --lines=1 | awk -F: '{{print $1}}')"
local tmp_file=$(mktemp)
head --lines=$(($start - 1)) "$file" >"$tmp_file"
tail --lines=+$(($start + 1)) "$file" >>"$tmp_file"
mv "$tmp_file" "$file"
}