#!/bin/bash
# -*- coding: utf-8 -*-
# Timestamp: "2025-11-11 07:23:33 (ywatanabe)"
# File: ./scripts/shell/modules/check_dependancy_commands.sh
ORIG_DIR="$(pwd)"
THIS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LOG_PATH="$THIS_DIR/.$(basename "$0").log"
echo >"$LOG_PATH"
GRAY='\033[0;90m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
RED='\033[0;31m'
NC='\033[0m' # No Color
echo_info() { echo -e "${GRAY}INFO: $1${NC}"; }
log_info() {
if [ "${SCITEX_LOG_LEVEL:-1}" -ge 2 ]; then
echo -e " \033[0;90m→ $1\033[0m"
fi
}
echo_success() { echo -e "${GREEN}SUCC: $1${NC}"; }
echo_warning() { echo -e "${YELLOW}WARN: $1${NC}"; }
echo_error() { echo -e "${RED}ERRO: $1${NC}"; }
echo_header() { echo_info "=== $1 ==="; }
# ---------------------------------------
# Don't clear log at start - timing info will be appended
# Configurations
source ./config/load_config.sh "$SCITEX_WRITER_DOC_TYPE"
# Source the 00_shared LaTeX commands module
source "$(dirname "${BASH_SOURCE[0]}")/command_switching.src"
log_info "Running ${BASH_SOURCE[0]}..."
# Detect package manager
detect_package_manager() {
if command -v apt &>/dev/null; then
echo "apt"
elif command -v yum &>/dev/null; then
echo "yum"
else
echo "unknown"
fi
}
# Check if sudo is available
has_sudo() {
if command -v sudo &>/dev/null; then
return 0
else
return 1
fi
}
PKG_MANAGER=$(detect_package_manager)
SUDO_PREFIX=""
if has_sudo; then
SUDO_PREFIX="sudo "
fi
# Standalone checker for each tool
check_pdflatex() {
local cmd
cmd=$(get_cmd_pdflatex "$ORIG_DIR")
if [ -z "$cmd" ]; then
echo "- pdflatex"
if [ "$PKG_MANAGER" = "apt" ]; then
echo " - ${SUDO_PREFIX}apt install texlive-latex-base"
elif [ "$PKG_MANAGER" = "yum" ]; then
echo " - ${SUDO_PREFIX}yum install texlive-latex"
fi
echo " - Or use: module load texlive"
echo " - Or use: apptainer/singularity with texlive container"
return 1
fi
return 0
}
check_bibtex() {
local cmd
cmd=$(get_cmd_bibtex "$ORIG_DIR")
if [ -z "$cmd" ]; then
echo "- bibtex"
if [ "$PKG_MANAGER" = "apt" ]; then
echo " - ${SUDO_PREFIX}apt install texlive-bibtex-extra"
elif [ "$PKG_MANAGER" = "yum" ]; then
echo " - ${SUDO_PREFIX}yum install texlive-bibtex"
fi
echo " - Or use: module load texlive"
echo " - Or use: apptainer/singularity with texlive container"
return 1
fi
return 0
}
check_latexdiff() {
local cmd
cmd=$(get_cmd_latexdiff "$ORIG_DIR")
if [ -z "$cmd" ]; then
echo "- latexdiff"
if [ "$PKG_MANAGER" = "apt" ]; then
echo " - ${SUDO_PREFIX}apt install latexdiff"
elif [ "$PKG_MANAGER" = "yum" ]; then
echo " - ${SUDO_PREFIX}yum install texlive-latexdiff"
fi
echo " - Or use: module load texlive"
echo " - Or use: apptainer/singularity with texlive container"
return 1
fi
return 0
}
check_texcount() {
local cmd
cmd=$(get_cmd_texcount "$ORIG_DIR")
if [ -z "$cmd" ]; then
echo "- texcount"
if [ "$PKG_MANAGER" = "apt" ]; then
echo " - ${SUDO_PREFIX}apt install texlive-extra-utils"
elif [ "$PKG_MANAGER" = "yum" ]; then
echo " - ${SUDO_PREFIX}yum install texlive-texcount"
fi
echo " - Or use: module load texlive"
echo " - Or use: apptainer/singularity with texlive container"
return 1
fi
return 0
}
check_xlsx2csv() {
if ! command -v xlsx2csv &>/dev/null && ! python3 -c "import xlsx2csv" &>/dev/null 2>&1; then
echo "- xlsx2csv"
echo " - pip install xlsx2csv"
if [ "$PKG_MANAGER" = "apt" ]; then
echo " - Or: ${SUDO_PREFIX}apt install xlsx2csv"
fi
return 1
fi
return 0
}
check_csv2latex() {
if ! command -v csv2latex &>/dev/null && ! python3 -c "import csv2latex" &>/dev/null 2>&1; then
echo "- csv2latex"
echo " - pip install csv2latex"
return 1
fi
return 0
}
check_parallel() {
if ! command -v parallel &>/dev/null; then
echo "- parallel"
if [ "$PKG_MANAGER" = "apt" ]; then
echo " - ${SUDO_PREFIX}apt install parallel"
elif [ "$PKG_MANAGER" = "yum" ]; then
echo " - ${SUDO_PREFIX}yum install parallel"
fi
return 1
fi
return 0
}
check_opencv() {
if command -v python3 &>/dev/null; then
if ! python3 -c "import cv2" &>/dev/null 2>&1; then
echo "- opencv-python (optional, for --crop_tif)"
echo " - pip install opencv-python"
return 1
fi
fi
return 0
}
check_numpy() {
if command -v python3 &>/dev/null; then
if ! python3 -c "import numpy" &>/dev/null 2>&1; then
echo "- numpy (optional, for --crop_tif)"
echo " - pip install numpy"
return 1
fi
fi
return 0
}
check_mmdc() {
local cmd
cmd=$(get_cmd_mmdc "$ORIG_DIR")
if [ -z "$cmd" ]; then
echo "- mmdc (optional, for Mermaid diagrams)"
if ! command -v npm &>/dev/null; then
echo " - First install npm/nodejs"
fi
echo " - npm install -g @mermaid-js/mermaid-cli"
echo " - Or use: apptainer/singularity with mermaid container"
return 1
fi
return 0
}
check_bibtexparser() {
if command -v python3 &>/dev/null; then
if ! python3 -c "import bibtexparser" &>/dev/null 2>&1; then
echo "- bibtexparser (for bibliography analysis tools)"
echo " - pip install bibtexparser"
return 1
fi
fi
return 0
}
# Check all required commands (parallelized for speed)
check_all_dependencies() {
local has_missing_required=false
local has_missing_optional=false
local required_output=""
local optional_output=""
# Log run timestamp
echo "=== $(date '+%Y-%m-%d %H:%M:%S') ===" >>"$LOG_PATH"
# Quick native-only check to avoid expensive container warmup
local all_native_available=true
local start_native_check
start_native_check=$(date +%s%N)
# Check if all required native commands exist (fast check only)
if ! command -v pdflatex &>/dev/null || ! pdflatex --version &>/dev/null 2>&1; then
all_native_available=false
elif ! command -v bibtex &>/dev/null || ! bibtex --version &>/dev/null 2>&1; then
all_native_available=false
elif ! command -v latexdiff &>/dev/null; then
all_native_available=false
elif ! command -v texcount &>/dev/null || ! texcount --version &>/dev/null 2>&1; then
all_native_available=false
fi
local end_native_check
end_native_check=$(date +%s%N)
local native_check_ms
native_check_ms=$(((end_native_check - start_native_check) / 1000000))
echo "Native check: ${native_check_ms}ms" >>"$LOG_PATH"
echo_info " Native check: ${native_check_ms}ms"
# Only do expensive warmup if native commands are missing
if [ "$all_native_available" = false ]; then
echo_info " Native commands incomplete, checking alternatives..."
# Pre-warmup: do expensive shared setup once before parallelizing
# This prevents each parallel job from doing redundant work
local start_warmup
start_warmup=$(date +%s%N)
get_container_runtime &>/dev/null
load_texlive_module &>/dev/null
setup_latex_container &>/dev/null
setup_mermaid_container &>/dev/null
local end_warmup
end_warmup=$(date +%s%N)
local warmup_ms
warmup_ms=$(((end_warmup - start_warmup) / 1000000))
echo "Warmup: ${warmup_ms}ms" >>"$LOG_PATH"
echo_info " Warmup: ${warmup_ms}ms"
else
echo_info " All native LaTeX commands available (skipping container warmup)"
fi
# Temp directory for parallel results
local temp_dir
temp_dir=$(mktemp -d)
# Run all required checks in parallel, capturing exit codes
local start_checks
start_checks=$(date +%s%N)
(
check_pdflatex >"$temp_dir/req_pdflatex" 2>&1
echo $? >"$temp_dir/req_pdflatex.exit"
) &
(
check_bibtex >"$temp_dir/req_bibtex" 2>&1
echo $? >"$temp_dir/req_bibtex.exit"
) &
(
check_latexdiff >"$temp_dir/req_latexdiff" 2>&1
echo $? >"$temp_dir/req_latexdiff.exit"
) &
(
check_texcount >"$temp_dir/req_texcount" 2>&1
echo $? >"$temp_dir/req_texcount.exit"
) &
(
check_xlsx2csv >"$temp_dir/req_xlsx2csv" 2>&1
echo $? >"$temp_dir/req_xlsx2csv.exit"
) &
(
check_csv2latex >"$temp_dir/req_csv2latex" 2>&1
echo $? >"$temp_dir/req_csv2latex.exit"
) &
(
check_parallel >"$temp_dir/req_parallel" 2>&1
echo $? >"$temp_dir/req_parallel.exit"
) &
(
check_bibtexparser >"$temp_dir/req_bibtexparser" 2>&1
echo $? >"$temp_dir/req_bibtexparser.exit"
) &
# Run all optional checks in parallel
(
check_opencv >"$temp_dir/opt_opencv" 2>&1
echo $? >"$temp_dir/opt_opencv.exit"
) &
(
check_numpy >"$temp_dir/opt_numpy" 2>&1
echo $? >"$temp_dir/opt_numpy.exit"
) &
(
check_mmdc >"$temp_dir/opt_mmdc" 2>&1
echo $? >"$temp_dir/opt_mmdc.exit"
) &
# Wait for all background jobs
wait
local end_checks
end_checks=$(date +%s%N)
local checks_ms
checks_ms=$(((end_checks - start_checks) / 1000000))
echo "Parallel checks: ${checks_ms}ms" >>"$LOG_PATH"
echo_info " Parallel checks: ${checks_ms}ms"
# Collect required results with exit codes
declare -A tool_status
local exit_code
for tool in pdflatex bibtex latexdiff texcount xlsx2csv csv2latex parallel bibtexparser; do
exit_code=$(cat "$temp_dir/req_${tool}.exit" 2>/dev/null || echo 1)
if [ "$exit_code" -eq 0 ]; then
tool_status[$tool]="✓"
else
has_missing_required=true
tool_status[$tool]="✗"
if [ -s "$temp_dir/req_${tool}" ]; then
required_output="${required_output}$(cat "$temp_dir/req_${tool}")\n"
fi
fi
done
# Collect optional results
local tool
for result_file in "$temp_dir"/opt_*.exit; do
tool=$(basename "$result_file" .exit | sed 's/opt_//')
exit_code=$(cat "$result_file" 2>/dev/null || echo 1)
if [ "$exit_code" -ne 0 ]; then
has_missing_optional=true
if [ -s "${result_file%.exit}" ]; then
optional_output="${optional_output}$(cat "${result_file%.exit}")\n"
fi
fi
done
# Cleanup
rm -rf "$temp_dir"
# Display results
if [ "$has_missing_required" = true ]; then
echo_error " Missing required tools:"
echo -e "$required_output"
return 1
else
# Show summary table using cached results (no additional checks!)
echo_success " Required tools:"
printf " %-20s %s\n" "pdflatex" "${tool_status[pdflatex]}"
printf " %-20s %s\n" "bibtex" "${tool_status[bibtex]}"
printf " %-20s %s\n" "latexdiff" "${tool_status[latexdiff]}"
printf " %-20s %s\n" "texcount" "${tool_status[texcount]}"
printf " %-20s %s\n" "xlsx2csv" "${tool_status[xlsx2csv]}"
printf " %-20s %s\n" "csv2latex" "${tool_status[csv2latex]}"
printf " %-20s %s\n" "parallel" "${tool_status[parallel]}"
printf " %-20s %s\n" "bibtexparser" "${tool_status[bibtexparser]}"
fi
if [ "$has_missing_optional" = true ]; then
echo_warning " Missing optional tools:"
echo -e "$optional_output"
fi
return 0
}
# Run checks
check_all_dependencies
exit_code=$?
exit $exit_code
# EOF