lackadaisical/daisy.source
2025-12-31 16:06:50 +01:00

504 lines
12 KiB
Text
Executable file

#!/bin/echo "This file can only be sourced, not run stand-alone." -- #!/bin/bash
# LACKADAISICAL SOURCE-ABLE FILE
# Source this in your RC file or manually to receive some of the simpler
# utilities, as well as aliases for `shrc` and `cdf`. Set env variable
# FROM_RC to 1 when sourcing this file to get RC-related functionality:
# FROM_RC=1 source <lackadaisical-root>/daisy.source
# This file is also sourced in some of the scripts included within
# lackadaisical for common functionality. Some of the shared functionality is
# only included if sourced from one of the included scripts, though you are
# free to bypass this by setting env variable LD_INTERNAL to 1.
if [[ $LD_INTERNAL -eq 1 ]];
then
export LD_BIN=$(basename $0)
fi
# Variables for use in other utilities
# Find the right argument for our folder
arg=$0
if [[ ! $arg == *daisy.source* ]];
then
arg="${BASH_SOURCE[0]}"
fi
# Check for dependencies
function daisy_dependency_check
{
BIN=$(command -v $1 2>/dev/null)
res=$?
BIN=$(basename $BIN 2>/dev/null)
if [[ $BIN == $1 ]]; then
res=1
fi
echo $(($res ^ 1))
}
LD_HAS_fzf=$(daisy_dependency_check fzf)
LD_HAS_md5sum=$(daisy_dependency_check md5sum)
LD_HAS_peco=$(daisy_dependency_check peco)
LD_HAS_tree=$(daisy_dependency_check tree)
export LD_FOLDER=$(dirname $(realpath $arg))
export LD_SOURCE_FILE=$(realpath $arg)
export LD_AVAILABLE=0
# Config folder setup
export LD_CONFIG_FOLDER="$HOME/.config/lackadaisical"
new_install=0
if [[ ! -d "$LD_CONFIG_FOLDER" ]];
then
# Create the folder with its basics
mkdir -p "$LD_CONFIG_FOLDER"
daisy_help
new_install=1
fi
# Multiple default source files
# [LEA.TODO] Turn these into arrays
LD_ALIASFILE="$LD_CONFIG_FOLDER/aliases.src"
LD_EDITORFILE="$LD_CONFIG_FOLDER/editor.src"
touch $LD_ALIASFILE
touch $LD_EDITORFILE
# Source everything in the config folder
function _daisy_source_configs
{
for f in `find "$LD_CONFIG_FOLDER" -name "*.src" -type f`;
do
source "$f"
done
}
# Installation into PATH
if [[ ! $PATH == *"$LD_FOLDER"* ]];
then
export PATH="$PATH:$LD_FOLDER"
fi
# Set up the basic alias for `shrc`
# Do not set these up if LD_INTERNAL=1 is set, or infinite recursion could
# occur!
if [[ ! -v LD_INTERNAL ]];
then
alias shrc=". shrc"
fi
###############################################################################
# FUNCTIONS and ALIASES #######################################################
###############################################################################
# bak and unbak
function bak
{
# Input: <file>
target=$1
# Check if file exists
if ! test -f "$target";
then
echo "Path not found: \"$target\""
return 2
fi
# Handle both cases
if [[ $unbak_mode -eq 1 ]];
then
cp -R "$target.bak" "$target"
rm -rf "$target.bak"
echo "Restored backup: $target <-- $target.bak"
else
cp -R "$target" "$target.bak"
echo "Backup made: $target --> $target.bak"
fi
}
alias unbak="unbak_mode=1 bak"
alias lsa="ls -a -l -h"
alias lsn="ls -a -l -tu -r -h"
alias lss="ls -a -l -S -r -h"
# Simple version of `cdf`
function cdf
{
if [[ $LD_HAS_fzf != 1 ]];
then
echo "This alias requires the utility 'fzf'. Please install it."
return 1
fi
cd $(dirname $(fzf))
}
function cdp
{
if [[ $LD_HAS_peco != 1 || $LD_HAS_tree != 1 ]];
then
echo "This alias requires the utilities 'peco' and 'tree'. Please install them."
echo "Consider using 'cdf' instead."
return 1
fi
cd $(dirname $(tree -fia --noreport . | peco))
}
function editpeco
{
if [[ $LD_HAS_peco != 1 || $LD_HAS_tree != 1 ]];
then
echo "This alias requires the utilities 'peco' and 'tree'. Please install them."
echo "Consider using 'cdf' instead."
return 1
fi
tree --noreport -fia . | peco --prompt "Press CTRL+C to quit - query:" --exec "xargs -o -I{} $EDITOR {}"
}
# for convenience purposes
function editbin
{
editx $(which $1)
}
# sets a new editor based on commony available ones, and some visual ones
function ched
{
editors=("nano" "vim" "nvim" "vi" "emacs" "gedit" "kate" "mousepad" "micro" \
"code" "subl" "joe" "kwrite" "gnome-text-editor")
# Find which editors are installed
available_editors=()
for editor in "${editors[@]}";
do
editor_real=$(command -v "$editor")
if command -v "$editor_real" >/dev/null 2>&1;
then
if [[ $(realpath "$EDITOR") == "$editor_real" ]];
then
available_editors+=("$editor_real" "$editor (current choice)")
else
available_editors+=("$editor_real" "$editor")
fi
fi
done
if [[ ! -z $@ ]];
then
text="$@"
dialog --msgbox "$text" 0 0
fi
# Present all choices
choice=$(dialog --output-fd 1 --clear --title "Select Text Editor" \
--menu "Choose one of the installed text editors:" 15 50 6 \
"${available_editors[@]}")
dialog_ret=$?
if [ $dialog_ret -ne 0 ];
then
echo "No editor selected."
return
fi
echo export EDITOR=$choice > "$LD_EDITORFILE"
echo export LD_EDITOR=$choice >> "$LD_EDITORFILE"
echo export LD_OLD_EDITOR=$EDITOR >>"$LD_EDITORFILE"
_daisy_source_configs
}
function wait_for_editor
{
pname="$1"
fname="$2"
# Give some time for a process to launch
sleep 1
while true;
do
alive=$(ps aux | grep $fname | grep $pname)
if [[ $alive == "" ]]
then
break
fi
sleep 1
done
}
function daisy_reload
{
FROM_RC=0 source "$LD_SOURCE_FILE"
}
function ldrc
{
$EDITOR "$LD_SOURCE_FILE"
FROM_RC=0 source "$LD_SOURCE_FILE"
}
function daisy_enc
{
if [ -d $1 ];
then
echo -e "daisy_create_folder=$1"
else
file_info=$(file $1)
file_dir=$(dirname $1)
file_name=$(basename $1)
base64_inner=$(cat ${1:-/dev/stdin} | base64 | tr -d '\n')
# Print out our block
echo -e "daisy_folder_$file_name=$file_dir"
echo -e "daisy_data_base64_$file_name=\"$base64_inner\""
fi
}
# Will only take input files, always outputs to stdout
function daisy_enc_multi
{
for file in "$@"; do
daisy_enc "$file"
done
}
function daisy_enc_folder
{
if [[ $LD_HAS_tree != 1 ]];
then
echo "This function requires the utiliy 'tree'. Please install it."
return 1
fi
dir="$1"
cd "$dir"
tree -fia --noreport . | sed 1d | while read -r item;
do
daisy_enc "$item"
done
}
function daisy_dec
{
data=$(cat ${1:-/dev/stdin} | grep -v "#" )
echo -e "$data" | cut -d "=" -f 2- | cut -b 2- | head -c -2 | base64 -d
}
# Will only take a file and directory, sources it to find all encoded data
# Extracts to the directory
function daisy_dec_multi
{
[[ ! -f $1 ]] && echo "daisy_dec_multi: No input file specified" && return
[[ ! -d $2 ]] && echo "daisy_dec_multi: No output directory specified" && return
folder=
while IFS= read -r line; do
if [[ "$line" == "daisy_create_folder="* ]];
then
folder=$(echo $line | cut -d "=" -f 2)
mkdir -p "$2/$folder"
fi
if [[ "$line" == "daisy_folder"* ]];
then
folder=$(echo -e $line | cut -d "=" -f 2)
continue
fi
if [[ "$line" == "daisy_data_base64"* ]];
then
file=$(echo -e $line | cut -d "_" -f 4- | cut -d "=" -f 1)
daisy_dec <(echo $line) > "$2/$folder/$file"
fi
done <<< $(cat "$1")
}
# Saves a bit on typing
function grab
{
[[ -z $@ ]] && return;
awk '{print $'$1'}'
}
function daisy_unalias
{
unalias_param=$@
if [[ $unalias_param =~ '^[0-9]+$' ]]; then
selection=$(head -$unalias_param "$LD_ALIASFILE" | tail -1 | cut -d "=" -f 1 | grab 2)
daisy_unalias $selection
return
fi
if [[ -z $unalias_param ]]; then
return
fi
unalias $@ 2>/dev/null
# Remove from aliases list
newdata=$(cat "$LD_ALIASFILE" | grep -v "alias $unalias_param")
bak "$LD_ALIASFILE" 1>/dev/null
echo -e $newdata > "$LD_ALIASFILE"
}
function daisy_alias
{
alias_param="$@"
if [[ -z $alias_param ]]; then
linenum=1
echo "Active lackadaisical alias lines:"
while IFS= read -r line; do
line=$(echo "$line" | sed 's/alias / /g')
echo "$linenum: $line"
linenum=$(($linenum + 1))
done < "$LD_ALIASFILE"
return
fi
# Plain name and contents
alias_name=$(echo -e $alias_param | grep -o ".*=" | tr --delete =)
if [[ $alias_name =~ '^[0-9]+$' ]]; then
echo "An alias cannot start with a number! Exiting."
return 1
fi
# Make persistent
daisy_unalias $alias_name
echo alias ${alias_param%=*}"="\"${alias_param#*=}\" >> $LD_ALIASFILE
source $LD_ALIASFILE
}
_daisy_source_configs
###############################################################################
# end of FUNCTIONS and ALIASES ################################################
###############################################################################
# End of user section!
export LD_AVAILABLE=1
# Start of internal section
function daisy_quit_if_no
{
local dep_name="daisy_has_$1"
local has_dep="${!dep_name}"
# Check first if we have checked for this dependency, if not, print a fixme!
# TODO: Remove upon release, or convert into self-modifying code.
if [[ -z "$has_dep" ]];
then
echo "FIXME: Dependency `$1` should have an env variable, checking ad-hoc"
has_dep=$(daisy_dependency_check $1)
fi
if [[ $has_dep -eq 0 ]];
then
echo "$LD_BIN: The dependency $1 was not found! Please install it" \
"to be able to use this utility!"
exit 1
fi
}
[ -d "$LD_FOLDER" ] && export LD_AVAILABLE=1
# Help function, courtesy of Google Gemini
function daisy_help() {
local target_tool="$1"
local file="$LD_FOLDER/README.md"
# 1. Extract the block between the new headers
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., " - calm:" or " - bak/unbak:")
$0 ~ /^[[:space:]]*- / {
printing=0 # Stop printing previous tool
# Clean the line to get the "signature"
# " - bak/unbak:" becomes "bak/unbak"
sig = $0
sub(/^[[:space:]]*- /, "", sig)
sub(/:[[:space:]]*$/, "", sig)
# Check for exact match OR match within a slash-separated list
# This handles "bak", "unbak", and "daisy_alias"
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 # Print the header line (e.g., " - bak/unbak:")
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
}
# Courtesy of Google Gemini
daisy_list() {
local file="$LD_FOLDER/README.md"
echo "Available LACKADAISICAL commands:"
# Extract block -> Find tool lines -> Clean formatting -> Print
sed -n '/--- BEGIN OF DAISY HELP ---/,/--- END OF DAISY HELP ---/{//!p;}' "$file" |
awk '
/^[[:space:]]*- / {
# Remove indentation and "- "
sub(/^[[:space:]]*- /, "");
# Remove trailing ":"
sub(/:[[:space:]]*$/, "");
print " " $0
}
' | sort
}
# Hide what we don't need
if [[ ! -v LD_INTERNAL ]];
then
unset -f _daisy_source_configs
unset -f wait_for_editor
unset -f daisy_quit_if_no
unset -f daisy_dependency_check
unset LD_HAS_fzf
unset LD_HAS_peco
unset LD_HAS_md5sum
unset LD_HAS_tree
fi