: ' Changes:
Sat Apr 18 2026 Added csvi for edits, pspg for table view
'
[ "$1" == "-D" ] && DEBUG=1 && shift 1
[ "$DEBUG" == 1 ] && echo "---Variables---" && set -x
PS4='$SECONDS $LINENO: '
DOW=$(date +%a)
TODAY=$(date +%m/%d)
DOM=$(date +%d)
OS=$(uname -s)
NAME=${0##*/}
DIR="$(basename $PWD)"
PDIR="$(cd ..;basename $PWD)"
DB=~/db/contacts.csv
R=$(tput setaf 1)
BR=$(tput setaf 1; tput bold)
G=$(tput setaf 2)
BG=$(tput setaf 2; tput bold)
Y=$(tput setaf 3)
BY=$(tput setaf 3; tput bold)
B=$(tput setaf 4)
BM=$(tput setaf 5; tput bold)
BC=$(tput setaf 6; tput bold)
C=$(tput setaf 6)
BL=$(tput setaf 7; tput bold)
BLD=$(tput bold)
N=$(tput sgr0)
SIT=$(tput sitm)
RIT=$(tput ritm)
UL=$(tput smul)
NL=$(tput rmul)
RV=$(tput rev)
ROWS=$(tput lines)
COLS=$(tput cols)
[ "$DEBUG" == 1 ] && set +x && read -p "${N}-Continue-" -n 1 x
bl(){
[ "$DEBUG" == "1" ] && set -x
echo ""
}
html(){
vim -f +"syn on" +"set nonu" +"set foldenable!" +"set nospell" +"run! syntax/2html.vim" +"wq" +"q" $1
}
log(){
[ "$DEBUG" == "1" ] && set -x
logger -i -t "$NAME" "$*"
}
pause(){
[ "$DEBUG" == "1" ] && set -x
[ "$1" == "-nt" ] && TMOUT="" && shift
echo "$BY";
if [ $# -gt 0 ]
then
read -t $1 -r -p "${C}Hit any key (${BY}$1${C} second timeout)${N}" -n 1 FOO;
else
read -r -p "${C}Hit any key${N}" -n 1 FOO;
fi;
bl
}
strip-tags(){
sed -e 's/<[^>]*.//g' -
}
xtitle(){
printf "\033]0;%s\007" "$*"
}
add_record(){
local file="$DB"
local csv_dir=$(dirname "$file")
mkdir -p "$csv_dir"
if [[ ! -f "$file" ]]; then
echo "File $file not found. Define headers separated by comma (e.g., Name,Age,City):"
read -r header
echo "$header" > "$file"
fi
local header=$(head -n 1 "$file")
IFS=',' read -ra ADDR <<< "$header"
local new_record=""
for field in "${ADDR[@]}"; do
field=$(echo "$field" | tr -d '\r')
read -p "Enter $field: " input
input="${input//\"/\"\"}"
new_record+="$input,"
done
echo "${new_record%,}" >> "$file"
echo "Record added to $file"
}
check_csv(){
local file="$DB"
if [[ -f "$file" ]]; then
echo "--- CSV Stats: $file ---"
echo "Total Rows: $(wc -l < "$file")"
echo "Total Columns: $(head -n 1 "$file" | awk -F, '{print NF}')"
echo "Headers: $(head -n 1 "$file" | sed 's/,/, /g')"
du -sh "$file"
echo "--------------------------"
else
echo "File not found: $file"
fi
}
view_record() {
local search="$1"
local file="$2"
awk -F, -v s="$search" '
NR==1 {for (i=1; i<=NF; i++) h[i]=$i; next} # Store header
{IGNORECASE=1}
$0 ~ s { # If line matches
print "--- Record Found ---"
for (i=1; i<=NF; i++) {
printf "%-15s: %s\n", h[i], $i
}
}
' "$file"
}
view_csv() {
if [ -z "$1" ]; then
echo "Usage: view_csv_pretty <file.csv>"
else
cat "$1" | column -s, -t | less -F -S -X -K
fi
}
if [ "$1" == "-E" ]
then
vim $0
sed -i -e "7s/.*/# Updated....: $(date)/" $0
html $0
cp $0 /var/www/unix
mv $0.html /var/www/unix
log "Updated $0"
exit
fi
if [ "$1" == "-h" ] || [ "$1" == "--help" ]
then
fmt -s -w $(tput cols) <<END
${BC}$NAME${N} ${SIT}A contact list manager${RIT}
${BY}Options:${N}
-a # Add entry
-c # Check csv
-e # Edit table
-l # list view
{string} find someone
END
exit
fi
command -v bash >/dev/null || sudo apt install bash -qyy
command -v pspg >/dev/null || echo "Required https://github.com/okbob/pspg"
command -v csvi >/dev/null || echo "Required https://hymkor.github.io/csvi/"
[ "$DEBUG" == 1 ] && echo "---Functions---" && typeset -F && read -p "${N}-Continue-" -n 1 x
[ "$DEBUG" == 1 ] && echo "---Main---" && set -x
[ "$#" -eq 0 ] && $0 -h && exit
case "$1" in
-a)
add_record
pspg $DB
;;
-c)
check_csv
;;
-e)
csvi $DB
;;
-l)
pspg $DB
;;
*)
echo $BC
view_record "$1" $DB |sed -e "0,/${1}/I s/${1}/${BY}${1^}${BC}/I"
;;
esac
exit