#! /usr/bin/env sh # Copyright (C) 2023 - 2024: # The Trinitrix Project # SPDX-License-Identifier: GPL-3.0-or-later # # This file is part of the Trixy crate for Trinitrix. # # Trixy is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as # published by the Free Software Foundation, either version 3 of # the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # and the GNU General Public License along with this program. # If not, see . # Parts of a shell library {{{ die() { error "$1" if [ -n "$2" ]; then exit "$2" else exit 1 fi } print() { # The direct usage is intended as `print` is rather lowlevel # shellcheck disable=2059 printf "$*" } println() { # The direct usage is intended as `println` is rather lowlevel # shellcheck disable=2059 printf "$*\n" } eprint() { >&2 print "$@" } eprintln() { >&2 println "$@" } if [ -n "$NO_COLOR" ]; then error() { eprintln "==> ERROR:" "$*" } warning() { eprintln "==> WARNING:" "$*" } debug() { [ -n "$SHELL_LIBRARY_DEBUG" ] && eprintln "==> [Debug:]" "$*" } debug2() { [ -n "$SHELL_LIBRARY_DEBUG" ] && eprintln " -> [Debug:]" "$*" } msg() { eprintln "==>" "$*" } msg2() { eprintln " ->" "$*" } prompt() { eprint "..>" "$*" } else # See https://stackoverflow.com/a/33206814 for ansi codes error() { eprintln "\033[1;91m==> ERROR:\033[0m" "\033[1;93m$*\033[0m" } warning() { eprintln "\033[1;91m==> WARNING:\033[0m" "\033[1;93m$*\033[0m" } debug() { [ -n "$SHELL_LIBRARY_DEBUG" ] && eprintln "\033[1;94m==> [Debug:]\033[0m" "\033[1;93m$*\033[0m" } debug2() { [ -n "$SHELL_LIBRARY_DEBUG" ] && eprintln "\033[1;94m -> [Debug:]\033[0m" "\033[1;93m$*\033[0m" } msg() { eprintln "\033[1;96m==>\033[0m" "\033[1;93m$*\033[0m" } msg2() { eprintln "\033[1;96m ->\033[0m" "\033[1;93m$*\033[0m" } prompt() { eprint "\033[1;96m..>\033[0m" "\033[1;93m$*\033[0m" } fi mktmp() { ensure_tmp_dir mktemp -p "$SHELL_LIBRARY_TEMP_PREFIX_DIR" } ensure_tmp_dir() { if ! [ -d "$SHELL_LIBRARY_TEMP_PREFIX_DIR" ]; then SHELL_LIBRARY_TEMP_PREFIX_DIR="$(mktemp -d)" fi } # A new version of tmp, which allows you to specify the commandline args as normal # arguments tmp() { if echo "$1" | grep -E ' ' -q; then warn "Detected an old version of tmp, as there are spaces in the input string!" fi TEMP_DIR_WITH_DEL="$(mktmp)" "$@" 1>"$TEMP_DIR_WITH_DEL" echo "$TEMP_DIR_WITH_DEL" } # Takes a path to search as argument. # Also takes further arguments as names to search for. # Prints the path to a file, if a file matching the given name is found. search_dir_for_file() { [ -d "$1" ] || die "Arg $1 is not a directory" directory="$1" && shift 1 while read -r dir_entry; do dir_entry_count=$((dir_entry_count + 1)) dir_entry_basename="$(basename "$dir_entry")" for name in "$@"; do if [ "$name" = "$dir_entry_basename" ]; then println "$dir_entry" fi done done <"$(tmp fd . "$directory" --type file --max-depth 1)" print "" } # Returns the path to the directory which contains all the specified files: # `search_upward_files file1 file2 file3` returns a path containing file1 ... search_upward_files() { directory="$(pwd)" final_directory="" output="$(mktmp)" while [ "$(wc -l <"$output")" = 0 ]; do search_dir_for_file "$directory" "$@" >"$output" directory="$(dirname "$directory")" if [ "$directory" = "/" ]; then warning "We bailed out, as there seems to be no directory containing $*" final_directory="" return fi done final_directory="$(dirname "$(head -n1 "$output")")" print "$final_directory" } # }}} help() { cat <