lackadaisical/daisy.command.source

424 lines
10 KiB
Bash
Executable file

#!/usr/bin/env bash
# LACKADAISICAL CLI
# Environment Setup
LD_CONFIG_FOLDER="${LD_CONFIG_FOLDER:-$HOME/.config/lackadaisical}"
LD_ALIASFILE="${LD_ALIASFILE:-$LD_CONFIG_FOLDER/aliases.src}"
LD_EDITORFILE="${LD_EDITORFILE:-$LD_CONFIG_FOLDER/editor.src}"
LD_ESOURCEFILE="${LD_ESOURCEFILE:-$LD_CONFIG_FOLDER/extra.src}"
if [[ -z "$LD_FOLDER" ]]; then
LD_FOLDER=$(dirname "$(realpath "$0")")
fi
ld_dbg()
{
if [[ $_LD_DEBUG == 1 ]]; then
echo "DEBUG: $*" >&2
fi
}
cmd_editor()
{
local editor=${LD_EDITOR:-$EDITOR}
ld_dbg "Opening $editor to edit file: $1"
$editor "$1"
}
_daisy_enc()
{
local enc_is_folder="${ENC_IS_FOLDER:-0}"
if [ -t 0 ] && [ -z "$1" ]; then
echo "# $0: No arguments or stdin specified!"
return 1
fi
if [ ! -t 0 ] && [ -z "$1" ]; then
echo "# $0: Please provide a filename as argument when using stdin"
return 1
fi
if [ -n "$1" ] && [ -d "$1" ]; then
echo -e "daisy_create_folder=$1"
else
local file_dir=""
local file_name=""
local perms=755
local target=$1
if [[ ! -t 0 ]] && [[ $enc_is_folder == 0 ]]; then
file_dir="."
file_name="$1"
elif [ -f "$1" ]; then
file_dir=$(dirname "$1")
file_name=$(basename "$1")
perms=$(stat -c %a "$1")
else
echo "# $0: An error occured during encoding."
return 1
fi
local base64_inner
base64_inner=$(cat "${1:-/dev/stdin}" | base64 | tr -d '\n')
echo -e "daisy_folder_$file_name=$file_dir"
echo -e "daisy_data_base64_$file_name=\"$base64_inner\""
echo -e "daisy_perms_$file_name=$perms"
fi
}
_daisy_dec()
{
if [ -t 0 ] && [ -z "$1" ]; then
echo "$0: No arguments or stdin specified!"
return 1
fi
local data
data=$(cat "${1:-/dev/stdin}" | grep -v "#")
echo -e "$data" | cut -d "=" -f 2- | cut -b 2- | head -c -2 | base64 -d
}
_daisy_unalias()
{
local unalias_param="$1"
if [[ $unalias_param =~ ^[0-9]+$ ]]; then
unalias_param=$(head -"$unalias_param" "$LD_ALIASFILE" 2>/dev/null | tail -1 | cut -d "=" -f 1 | awk '{print $2}')
fi
if [[ -z "$unalias_param" ]]; then
return
fi
if [[ -f "$LD_ALIASFILE" ]]; then
local newdata
newdata=$(grep -v "alias $unalias_param" "$LD_ALIASFILE" 2>/dev/null)
cp "$LD_ALIASFILE" "$LD_ALIASFILE.bak" 2>/dev/null
echo -e "$newdata" > "$LD_ALIASFILE"
fi
source "$LD_ALIASFILE"
echo "Sourcing..."
}
# --- Command Functions ---
cmd_help()
{
local target_tool="$1"
local file="$LD_FOLDER/README.md"
# 1. Extract the block between the help markers
sed -n '/--- BEGIN OF DAISY HELP ---/,/--- END OF DAISY HELP ---/{//!p;}' "$file" |
if [ -z "$target_tool" ]; then
# If no argument, print the whole help text
cat
else
# 2. Parse specific tool
awk -v query="$target_tool" '
BEGIN { found=0; printing=0 }
# Match lines defining tools (e.g., "< cdz >" or "< daisy welcome >")
$0 ~ /^[[:space:]]*< .* >/ {
printing=0 # Stop printing previous tool
# Clean the line to get the "signature"
# "< daisy welcome >" becomes "daisy welcome"
sig = $0
sub(/^[[:space:]]*< /, "", sig)
sub(/ >[[:space:]]*$/, "", sig)
# Check for exact match OR match within a slash/space-separated list
split(sig, names, "[ /]")
is_match = 0
if (sig == query) is_match = 1
else {
for (i in names)
{
if (names[i] == query)
{ is_match = 1; break }
}
}
if (is_match)
{
printing=1
found=1
print $0
next
}
}
# Print description lines if we are in a "found" block
printing {
# Stop if we hit the start of the NEXT tool
if ($0 ~ /^[[:space:]]*< /)
{ printing=0; next }
print
}
END {
if (found == 0)
{
print "Tool '"'"'" query "'"'"' not found in README.md."
}
}
'
fi
}
cmd_list()
{
local file="$LD_FOLDER/README.md"
if [[ ! -f "$file" ]]; then
echo "README.md not found at $file"
exit 1
fi
echo "Available LACKADAISICAL commands:"
sed -n '/--- BEGIN OF DAISY HELP ---/,/--- END OF DAISY HELP ---/{//!p;}' "$file" |
awk '
/^[[:space:]]*< / {
sub(/^[[:space:]]*< /, "");
sub(/ >[[:space:]]*$/, "");
print " " $0
}
' | sort
}
cmd_enc()
{
case "$1" in
multi)
shift
for f in "$@"; do _daisy_enc "$f"; done
;;
folder)
if ! command -v tree >/dev/null 2>&1; then
echo "This function requires the utility 'tree'. Please install it."
exit 1
fi
shift
local dir="$1"
if [[ ! -d "$dir" ]]; then
echo "Directory not found: $dir"
exit 1
fi
cd "$dir" || exit 1
tree -fia --noreport . | sed 1d | while read -r item; do
ENC_IS_FOLDER=1 _daisy_enc "$item"
done
;;
*)
_daisy_enc "$@"
;;
esac
}
cmd_dec()
{
case "$1" in
multi)
shift
local arg1=$1
local arg2=$2
if [ ! -t 0 ]; then
arg2=$1
arg1=/dev/stdin
fi
[[ -t 0 ]] && [[ ! -f "$arg1" ]] && echo "daisy dec multi: No input file specified" && exit 1
[[ ! -d "$arg2" ]] && echo "daisy dec multi: No output directory specified" && exit 1
local folder=""
while IFS= read -r line; do
if [[ "$line" == "daisy_create_folder="* ]]; then
folder=$(echo "$line" | cut -d "=" -f 2)
mkdir -p "$arg2/$folder"
elif [[ "$line" == "daisy_folder"* ]]; then
folder=$(echo "$line" | cut -d "=" -f 2)
elif [[ "$line" == "daisy_data_base64"* ]]; then
local file=$(echo "$line" | cut -d "_" -f 4- | cut -d "=" -f 1)
mkdir -p "$arg2/$folder"
_daisy_dec <(echo "$line") > "$arg2/$folder/$file"
elif [[ "$line" == "daisy_perms"* ]]; then
local file=$(echo "$line" | cut -d "_" -f 3- | cut -d "=" -f 1)
local perms=$(echo "$line" | cut -d "_" -f 3- | cut -d "=" -f 2)
chmod "$perms" "$arg2/$folder/$file"
fi
done < "$arg1"
;;
*)
_daisy_dec "$@"
;;
esac
}
cmd_alias()
{
local alias_param="$*"
if [[ -z "$alias_param" ]]; then
echo "Active lackadaisical alias lines:"
local linenum=1
if [[ -f "$LD_ALIASFILE" ]]; then
while IFS= read -r line; do
line=$(echo "$line" | sed 's/alias //g')
echo "$linenum: $line"
((linenum++))
done < "$LD_ALIASFILE"
fi
else
local alias_name=$(echo "$alias_param" | grep -o ".*=" | tr -d =)
if [[ $alias_name =~ ^[0-9]+$ ]]; then
echo "An alias cannot start with a number! Exiting."
exit 1
fi
_daisy_unalias "$alias_name"
echo "alias ${alias_param%=*}=\"${alias_param#*=}\"" >> "$LD_ALIASFILE"
fi
source "$LD_ALIASFILE"
echo "Sourcing..."
}
cmd_clear()
{
find "$LD_CONFIG_FOLDER" -name "*.src" -type f | while read -r f; do
cp -R "$f" "$f.bak"
echo "Removing config file: $f"
rm -rf "$f"
done
echo "Config cleared. Use 'daisy restore' if you would like to undo this."
}
cmd_restore()
{
find "$LD_CONFIG_FOLDER" -name "*.src.bak" -type f | while read -r f; do
local target="${f%.bak}"
cp -R "$f" "$target"
rm -rf "$f"
echo "Restored backup: $target <-- $f"
done
echo "Config restored. Backups have been retained."
}
cmd_check()
{
local failed=0
local output=""
check_bin()
{
str=""
if command -v "$1" >/dev/null 2>&1; then
str="[ \e[32mOK\e[0m ] $1\n"
else
str="[ \e[31m--\e[0m ] $1 ($2)\n"
failed=1
fi
output+=$str
echo -e -n "$str"
}
echo "--- Core (Essential) ---"
check_bin bash "Shell environment"
check_bin awk "Text processing"
check_bin sed "Stream editing"
check_bin grep "Pattern matching"
check_bin base64 "Data encoding"
check_bin realpath "Path resolution"
echo -e "\n--- Enhanced UI & Navigation ---"
check_bin fzf "Used by cdf"
check_bin peco "Used by cdp, editpeco"
check_bin tree "Used by cdp, editpeco, daisy_enc_folder"
check_bin dialog "Used by ched"
echo -e "\n--- Archives & Filesystems ---"
check_bin archivemount "Used by cdz (mounting)"
check_bin tar "Used by cdz (extraction)"
check_bin unzip "Used by cdz (extraction)"
check_bin unrar "Used by cdz (extraction)"
check_bin mksquashfs "Used by squasher make"
check_bin rsync "Used by squasher destroy"
check_bin sshfs "Used by sshp"
check_bin fusermount "Used by sshp, cdz"
echo -e "\n--- System ---"
check_bin sudo "Privilege escalation"
check_bin systemctl "Service management"
check_bin perl "Advanced error reporting"
echo "=========================================="
echo "Check complete."
echo "=========================================="
[[ DAISY_IGNORE_DEPS -eq 1 ]] && return 0
[[ $failed -eq 1 ]] && ex_msg="Missing packages. DAISY_IGNORE_DEPS=1 to override"
if [ $failed -eq 1 ] ; then
echo "Dependency report for LACKADAISICAL..."
echo "=========================================="
echo -e "$output"
echo "=========================================="
echo "Missing packages. DAISY_IGNORE_DEPS=1 to override"
return 1
fi
return 0
}
cmd_combine()
{
local cmds=()
local args=()
local separator_found=false
for item in "$@"; do
if [[ "$item" == "--" ]]; then
separator_found=true
continue
fi
if $separator_found; then
args+=("$item")
else
cmds+=("$item")
fi
done
for cmd in "${cmds[@]}"; do
set -- "${args[@]}"
eval "$cmd"
done
}
# --- Dispatcher ---
daisy ()
{
case "$1" in
help) shift; cmd_help "$@" ;;
list) shift; cmd_list "$@" ;;
enc) shift; cmd_enc "$@" ;;
dec) shift; cmd_dec "$@" ;;
alias) shift; cmd_alias "$@" ;;
unalias) shift; _daisy_unalias "$@" ;;
backup) shift; find "$LD_CONFIG_FOLDER" -name "*.src" -type f | while read -r f; do cp -R "$f" "$f.bak"; echo "Backup made: $f --> $f.bak"; done ;;
clear) shift; cmd_clear ;;
check) shift; cmd_check ;;
restore) shift; cmd_restore ;;
combine) shift; cmd_combine ;;
editor) shift; cmd_editor "$@" ;;
wait)
if [[ "$2" == "for" && "$3" == "editor" ]]; then
shift 3
_daisy_wait_for_editor "$@"
else
echo "Unknown daisy command: wait $*"
return 1
fi
;;
reload)
LD_INTERNAL=0 source "$LD_SOURCE_FILE"
;;
*)
echo "Unknown daisy command: $1"
return 1
;;
esac
}