2024-02-11

This commit is contained in:
ddidier/sphinx-doc 2023-10-14 21:06:27 +00:00 committed by Nicolas Boufidjeline
commit d654ae6731
29 changed files with 5392 additions and 0 deletions

1
bin/ansi Symbolic link
View file

@ -0,0 +1 @@
ansi-v2.0.4

1633
bin/ansi-v2.0.4/ansi Normal file

File diff suppressed because it is too large Load diff

15
bin/build-html.sh Executable file
View file

@ -0,0 +1,15 @@
#!/usr/bin/env bash
# ------------------------------------------------------------------------------
# Build the HTML Sphinx documentation.
#
# Examples:
# ./build-html.sh
# ./build-html.sh --name my-documentation
# ------------------------------------------------------------------------------
PROJECT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )"
"${PROJECT_DIR}/bin/build.sh" "${@}"
exit 0

15
bin/build-pdf.sh Executable file
View file

@ -0,0 +1,15 @@
#!/usr/bin/env bash
# ------------------------------------------------------------------------------
# Build the HTML and PDF Sphinx documentation.
#
# Examples:
# ./build-pdf.sh
# ./build-pdf.sh --name my-documentation
# ------------------------------------------------------------------------------
PROJECT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )"
"${PROJECT_DIR}/bin/build.sh" --pdf "${@}"
exit 0

162
bin/build.sh Executable file
View file

@ -0,0 +1,162 @@
#!/usr/bin/env bash
# ------------------------------------------------------------------------------
# Build the Sphinx documentation.
#
# Examples:
# ./build.sh
# ./build.sh --name my-documentation
# ------------------------------------------------------------------------------
PROJECT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )"
# shellcheck disable=SC1090
source "${PROJECT_DIR}/bin/shflags/shflags"
# shellcheck disable=SC1090
source "${PROJECT_DIR}/bin/ansi/ansi"
# shellcheck disable=SC1090
source "${PROJECT_DIR}/bin/ndd-log4b/ndd-log4b.sh"
# shellcheck disable=SC1090
source "${PROJECT_DIR}/bin/ndd-utils4b/ndd-utils4b.sh"
# shellcheck disable=SC1090
source "${PROJECT_DIR}/bin/variables.sh"
# disable before shflags
ndd::base::catch_more_errors_off
DEFINE_string "name" "${DDIDIER_SPHINX_CONTAINER_NAME}" "The name of the container" "n"
DEFINE_boolean "pdf" false "Enable PDF gneration" "p"
DEFINE_boolean "debug" false "Enable debug mode" "d"
read -r -d '' FLAGS_HELP <<EOF
Run Sphinx in build mode. Sphinx will build the documentation only once.
Examples:
./build.sh
EOF
# parse the command-line
FLAGS "$@" || exit $?
eval set -- "${FLAGS_ARGV}"
# enable after shflags
ndd::base::catch_more_errors_on
function main() {
if [[ "${FLAGS_debug}" -eq "${FLAGS_TRUE}" ]]; then
# shellcheck disable=SC2034
ndd::logger::set_stdout_level "DEBUG"
else
# shellcheck disable=SC2034
ndd::logger::set_stdout_level "INFO"
fi
local container_name
if [[ "${FLAGS_pdf}" -eq "${FLAGS_TRUE}" ]]; then
container_name="${FLAGS_name}-pdf"
else
container_name="${FLAGS_name}"
fi
if [[ -z "${container_name}" ]]; then
log error "┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log error "┃ The container name cannot be empty. Please use '-n' or '--name'"
log error "┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
exit 1
fi
local docker_image="ddidier/sphinx-doc:${DDIDIER_SPHINX_IMAGE_VERSION}"
local source_directory="${PROJECT_DIR}"
# $UID and $USER may not be defined
# local container_uid="${UID}"
# local container_username="${USER}"
local container_uid
local container_username
container_uid="$(id -u)"
container_username="$(id -u -n)"
if [[ -L "${source_directory}" ]]; then
log warning "The source directory cannot be a symbolic link."
source_directory="$(realpath "${source_directory}")"
fi
local sphinx_make_target
if [[ "${FLAGS_pdf}" -eq "${FLAGS_TRUE}" ]]; then
sphinx_make_target=latexpdf
else
sphinx_make_target=html
fi
log info "┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log info "┃ Building the Sphinx documentation"
log info "┃"
log info "┃ - using the Docker image: ${docker_image}"
log info "┃ - in the container: ${container_name}"
log info "┃ - as the user: ${container_username}"
log info "┃ - as the user ID: ${container_uid}"
log info "┃"
log info "┃ This container can usually be terminated with: Control+C"
log info "┃ But if this does not work: docker kill ${container_name}"
log info "┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
# Use the terminal if present
local docker_run_interactive=""
local docker_run_tty=""
if [[ -t 1 ]]; then
docker_run_interactive="-i"
docker_run_tty="-t"
fi
# echo \
# docker run --rm \
# ${docker_run_interactive} \
# ${docker_run_tty} \
# --name "${container_name}" \
# -e USER_ID="${container_uid}" \
# -e USER_NAME="${container_username}" \
# -v "${source_directory}":/data \
# "${docker_image}" \
# make --makefile=Makefile-sphinx "${sphinx_make_target}" "${@}" \
# || true
log info "$(ndd::print::script_output_start)"
docker run --rm \
${docker_run_interactive} \
${docker_run_tty} \
--name "${container_name}" \
-e USER_ID="${container_uid}" \
-e USER_NAME="${container_username}" \
-v "${source_directory}":/data \
"${docker_image}" \
make --makefile=Makefile-sphinx "${sphinx_make_target}" "${@}" \
|| true
log info "$(ndd::print::script_output_end)"
log info "┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log info "┃ BUILD -- Success! "
log info "┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
}
function error_handler() {
local error_code="$?"
test $error_code == 0 && return;
log error "An unexpected error has occured:\n%s" "$(ndd::base::print_stack_trace 2>&1)"
exit 1
}
trap 'error_handler ${?}' ERR
main "${@}"
exit 0

1
bin/ndd-log4b Symbolic link
View file

@ -0,0 +1 @@
ndd-log4b-0.3.0

View file

@ -0,0 +1,714 @@
#!/usr/bin/env bash
# ==============================================================================
# NDD Log4B -- A simple logger library for Bash.
#
# Copyright 2020 David DIDIER - All Rights Reserved
# Released under the MIT license (https://opensource.org/licenses/MIT)
#
# Author - David DIDIER
# Repository - https://gitlab.com/ddidier/bash-ndd-log4b
# Version - 0.3.0
# ------------------------------------------------------------------------------
#
# See https://gitlab.com/ddidier/bash-ndd-log4b for more details.
#
# ==============================================================================
set -o pipefail # trace ERR through pipes
set -o errtrace # trace ERR through 'time command' and other functions
set -o nounset # set -u : exit the script if you try to use an uninitialised variable
set -o errexit # set -e : exit the script if any statement returns a non-true return value
# ------------------------------------------------------------------------------
# Avoid sourcing this library more than one time
if [[ -n "${NDD_LOG4B_SOURCED+x}" ]] && [[ ${NDD_LOG4B_SOURCED} ]]; then
return 0
fi
NDD_LOG4B_SOURCED=true
# =============================================================== settings =====
# ------------------------------------------------------------------------------
# The color palette
#
_NDD_LOG4B_COLOR_RED=255,0,0
_NDD_LOG4B_COLOR_ORANGE=255,127,0
_NDD_LOG4B_COLOR_YELLOW=255,255,0
_NDD_LOG4B_COLOR_GREEN=0,255,0
_NDD_LOG4B_COLOR_BLUE=0,128,255
# ------------------------------------------------------------------------------
# The ordered logger levels.
declare -a NDD_LOG4B_LEVEL_NAMES
# ------------------------------------------------------------------------------
# The logger levels display names.
declare -A NDD_LOG4B_LEVEL_DISPLAY_NAMES
# ------------------------------------------------------------------------------
# The logger levels synonyms.
declare -A NDD_LOG4B_LEVEL_SYNONYMS
# ------------------------------------------------------------------------------
# The logger levels priorities (note that DISABLED = -1).
declare -A NDD_LOG4B_LEVEL_VALUES
# ------------------------------------------------------------------------------
# The logger levels look and feels as 'ansi' arguments.
declare -A NDD_LOG4B_LEVEL_ANSI_ARGS
# ------------------------------------------------------------------------------
# The settings of the stdout logger.
# The default level of the stdout appender
NDD_LOG4B_STDOUT_DEFAULT_LEVEL="WARNING"
# The default date format of the stdout appender ('date' command format)
NDD_LOG4B_STDOUT_DEFAULT_DATE_FORMAT="+%F %T"
# The message format of the stdout appender ('printf' command format)
# The accepted arguments are: date-time (%s), level (%s), message (%s)
NDD_LOG4B_STDOUT_DEFAULT_LOG_FORMAT="%s [%-5s] %s"
# The level of the stdout appender.
# This is a private variable. Use ndd::logger::set_stdout_level instead.
_NDD_LOG4B_STDOUT_LEVEL="${NDD_LOG4B_STDOUT_DEFAULT_LEVEL}"
# The date format of the stdout appender ('date' command format).
# This is a private variable. Use ndd::logger::set_stdout_date_format instead.
_NDD_LOG4B_STDOUT_DATE_FORMAT="${NDD_LOG4B_STDOUT_DEFAULT_DATE_FORMAT}"
# The message format of the stdout appender ('printf' command format).
# This is a private variable. Use ndd::logger::set_stdout_log_format instead.
_NDD_LOG4B_STDOUT_LOG_FORMAT="${NDD_LOG4B_STDOUT_DEFAULT_LOG_FORMAT}"
# ------------------------------------------------------------------------------
# The settings of the file logger.
# The default level of the stdout appender
NDD_LOG4B_FILE_DEFAULT_LEVEL="DISABLED"
# The default date format of the stdout appender ('date' command format)
NDD_LOG4B_FILE_DEFAULT_DATE_FORMAT="+%F %T"
# The default message format of the file appender ('printf' command format)
# The accepted arguments are: date-time (%s), level (%s), message (%s)
NDD_LOG4B_FILE_DEFAULT_LOG_FORMAT="%s [%-5s] %s"
# The level of the file appender.
# This is a private variable. Use ndd::logger::set_file_level instead.
_NDD_LOG4B_FILE_LEVEL="${NDD_LOG4B_FILE_DEFAULT_LEVEL}"
# The date format of the file appender ('date' command format).
# This is a private variable. Use ndd::logger::set_file_date_format instead.
_NDD_LOG4B_FILE_DATE_FORMAT="${NDD_LOG4B_FILE_DEFAULT_DATE_FORMAT}"
# The message format of the file appender ('printf' command format).
# The accepted arguments are: date-time (%s), level (%s), message (%s).
# This is a private variable. Use ndd::logger::set_file_log_format instead.
_NDD_LOG4B_FILE_LOG_FORMAT="${NDD_LOG4B_FILE_DEFAULT_LOG_FORMAT}"
# The file path of the file appender.
# This is a private variable. Use ndd::logger::set_file_path instead.
_NDD_LOG4B_FILE_PATH=
# ------------------------------------------------------------------------------
# A profile supporting RFC 5424:
#
# 0 - Emergency - system is unusable
# 1 - Alert - action must be taken immediately
# 2 - Critical - critical conditions
# 3 - Error - error conditions
# 4 - Warning - warning conditions
# 5 - Notice - normal but significant condition
# 6 - Informational - informational messages
# 7 - Debug - debug-level messages
#
function ndd::logger::profiles::use_rfc_5424() {
ndd::logger::profiles::_reset_levels
# The ordered logger levels.
NDD_LOG4B_LEVEL_NAMES[0]=EMERGENCY
NDD_LOG4B_LEVEL_NAMES[1]=ALERT
NDD_LOG4B_LEVEL_NAMES[2]=CRITICAL
NDD_LOG4B_LEVEL_NAMES[3]=ERROR
NDD_LOG4B_LEVEL_NAMES[4]=WARNING
NDD_LOG4B_LEVEL_NAMES[5]=NOTICE
NDD_LOG4B_LEVEL_NAMES[6]=INFORMATION
NDD_LOG4B_LEVEL_NAMES[7]=DEBUG
# The logger levels display names.
NDD_LOG4B_LEVEL_DISPLAY_NAMES["EMERGENCY"]="EMERG"
NDD_LOG4B_LEVEL_DISPLAY_NAMES["ALERT"]="ALERT"
NDD_LOG4B_LEVEL_DISPLAY_NAMES["CRITICAL"]="CRIT"
NDD_LOG4B_LEVEL_DISPLAY_NAMES["ERROR"]="ERROR"
NDD_LOG4B_LEVEL_DISPLAY_NAMES["WARNING"]="WARN"
NDD_LOG4B_LEVEL_DISPLAY_NAMES["NOTICE"]="NOTIC"
NDD_LOG4B_LEVEL_DISPLAY_NAMES["INFORMATION"]="INFO"
NDD_LOG4B_LEVEL_DISPLAY_NAMES["DEBUG"]="DEBUG"
# The logger levels synonyms.
NDD_LOG4B_LEVEL_SYNONYMS["EMERG"]="EMERGENCY"
NDD_LOG4B_LEVEL_SYNONYMS["CRIT"]="CRITICAL"
NDD_LOG4B_LEVEL_SYNONYMS["WARN"]="WARNING"
NDD_LOG4B_LEVEL_SYNONYMS["INFO"]="INFORMATION"
# The logger levels priorities (note that DISABLED = -1).
NDD_LOG4B_LEVEL_VALUES["DISABLED"]=-1
NDD_LOG4B_LEVEL_VALUES["EMERGENCY"]=0
NDD_LOG4B_LEVEL_VALUES["ALERT"]=1
NDD_LOG4B_LEVEL_VALUES["CRITICAL"]=2
NDD_LOG4B_LEVEL_VALUES["ERROR"]=3
NDD_LOG4B_LEVEL_VALUES["WARNING"]=4
NDD_LOG4B_LEVEL_VALUES["NOTICE"]=5
NDD_LOG4B_LEVEL_VALUES["INFORMATION"]=6
NDD_LOG4B_LEVEL_VALUES["DEBUG"]=7
# The logger levels look and feels as ansi arguments.
NDD_LOG4B_LEVEL_ANSI_ARGS["EMERGENCY"]=" --black --bg-rgb=${_NDD_LOG4B_COLOR_RED} --bold"
NDD_LOG4B_LEVEL_ANSI_ARGS["ALERT"]=" --black --bg-rgb=${_NDD_LOG4B_COLOR_ORANGE} --bold"
NDD_LOG4B_LEVEL_ANSI_ARGS["CRITICAL"]=" --black --bg-rgb=${_NDD_LOG4B_COLOR_YELLOW} --bold"
NDD_LOG4B_LEVEL_ANSI_ARGS["ERROR"]=" --rgb=${_NDD_LOG4B_COLOR_RED}"
NDD_LOG4B_LEVEL_ANSI_ARGS["WARNING"]=" --rgb=${_NDD_LOG4B_COLOR_ORANGE}"
NDD_LOG4B_LEVEL_ANSI_ARGS["NOTICE"]=" --rgb=${_NDD_LOG4B_COLOR_YELLOW}"
NDD_LOG4B_LEVEL_ANSI_ARGS["INFORMATION"]="--rgb=${_NDD_LOG4B_COLOR_GREEN}"
NDD_LOG4B_LEVEL_ANSI_ARGS["DEBUG"]=" --rgb=${_NDD_LOG4B_COLOR_BLUE}"
}
# ------------------------------------------------------------------------------
# A profile supporting Log4J levels:
#
# - Fatal
# - Error
# - Warning
# - Information
# - Debug
# - Trace
#
function ndd::logger::profiles::use_log4j() {
ndd::logger::profiles::_reset_levels
# The ordered logger levels.
NDD_LOG4B_LEVEL_NAMES[0]=FATAL
NDD_LOG4B_LEVEL_NAMES[1]=ERROR
NDD_LOG4B_LEVEL_NAMES[2]=WARNING
NDD_LOG4B_LEVEL_NAMES[3]=INFORMATION
NDD_LOG4B_LEVEL_NAMES[4]=DEBUG
NDD_LOG4B_LEVEL_NAMES[5]=TRACE
# The logger levels display names.
NDD_LOG4B_LEVEL_DISPLAY_NAMES["FATAL"]="FATAL"
NDD_LOG4B_LEVEL_DISPLAY_NAMES["ERROR"]="ERROR"
NDD_LOG4B_LEVEL_DISPLAY_NAMES["WARNING"]="WARN"
NDD_LOG4B_LEVEL_DISPLAY_NAMES["INFORMATION"]="INFO"
NDD_LOG4B_LEVEL_DISPLAY_NAMES["DEBUG"]="DEBUG"
NDD_LOG4B_LEVEL_DISPLAY_NAMES["TRACE"]="TRACE"
# The logger levels synonyms.
NDD_LOG4B_LEVEL_SYNONYMS["WARN"]="WARNING"
NDD_LOG4B_LEVEL_SYNONYMS["INFO"]="INFORMATION"
# The logger levels priorities (note that DISABLED = -1).
NDD_LOG4B_LEVEL_VALUES["DISABLED"]=-1
NDD_LOG4B_LEVEL_VALUES["FATAL"]=0
NDD_LOG4B_LEVEL_VALUES["ERROR"]=1
NDD_LOG4B_LEVEL_VALUES["WARNING"]=2
NDD_LOG4B_LEVEL_VALUES["INFORMATION"]=3
NDD_LOG4B_LEVEL_VALUES["DEBUG"]=4
NDD_LOG4B_LEVEL_VALUES["TRACE"]=5
# The logger levels look and feels as ansi arguments.
NDD_LOG4B_LEVEL_ANSI_ARGS["FATAL"]=" --black --bold --bg-red"
NDD_LOG4B_LEVEL_ANSI_ARGS["ERROR"]=" --red --bold"
NDD_LOG4B_LEVEL_ANSI_ARGS["WARNING"]=" --yellow --bold"
NDD_LOG4B_LEVEL_ANSI_ARGS["INFORMATION"]="--white-intense --bold"
NDD_LOG4B_LEVEL_ANSI_ARGS["DEBUG"]=""
NDD_LOG4B_LEVEL_ANSI_ARGS["TRACE"]=""
# The old look and feel with too many colors:
# NDD_LOG4B_LEVEL_ANSI_ARGS["FATAL"]=" --black --bg-rgb=${_NDD_LOG4B_COLOR_RED} --bold"
# NDD_LOG4B_LEVEL_ANSI_ARGS["ERROR"]=" --rgb=${_NDD_LOG4B_COLOR_RED}"
# NDD_LOG4B_LEVEL_ANSI_ARGS["WARNING"]=" --rgb=${_NDD_LOG4B_COLOR_ORANGE}"
# NDD_LOG4B_LEVEL_ANSI_ARGS["INFORMATION"]="--rgb=${_NDD_LOG4B_COLOR_YELLOW}"
# NDD_LOG4B_LEVEL_ANSI_ARGS["DEBUG"]=" --rgb=${_NDD_LOG4B_COLOR_GREEN}"
# NDD_LOG4B_LEVEL_ANSI_ARGS["TRACE"]=" --rgb=${_NDD_LOG4B_COLOR_BLUE}"
}
# ------------------------------------------------------------------------------
# A profile enabling JSON output on stdout.
#
# Globals:
# _NDD_LOG4B_STDOUT_DATE_FORMAT
# _NDD_LOG4B_STDOUT_LOG_FORMAT
#
function ndd::logger::profile::use_json_for_stdout() {
_NDD_LOG4B_STDOUT_DATE_FORMAT="+%s"
_NDD_LOG4B_STDOUT_LOG_FORMAT='{"timestamp":"%s","level":"%s","message":"%s"}'
}
# ------------------------------------------------------------------------------
# A profile enabling JSON output to the file.
#
# Globals:
# _NDD_LOG4B_FILE_DATE_FORMAT
# _NDD_LOG4B_FILE_LOG_FORMAT
#
function ndd::logger::profile::use_json_for_file() {
_NDD_LOG4B_FILE_DATE_FORMAT="+%s"
_NDD_LOG4B_FILE_LOG_FORMAT='{"timestamp":"%s","level":"%s","message":"%s"}'
}
# ------------------------------------------------------------------------------
# Reset the current profile.
# Must be called before redefining the levels.
#
function ndd::logger::profiles::_reset_levels() {
for i in "${!NDD_LOG4B_LEVEL_NAMES[@]}"; do
unset NDD_LOG4B_LEVEL_NAMES["$i"]
done
for i in "${!NDD_LOG4B_LEVEL_DISPLAY_NAMES[@]}"; do
unset NDD_LOG4B_LEVEL_DISPLAY_NAMES["$i"]
done
for i in "${!NDD_LOG4B_LEVEL_SYNONYMS[@]}"; do
unset NDD_LOG4B_LEVEL_SYNONYMS["$i"]
done
for i in "${!NDD_LOG4B_LEVEL_VALUES[@]}"; do
unset NDD_LOG4B_LEVEL_VALUES["$i"]
done
for i in "${!NDD_LOG4B_LEVEL_ANSI_ARGS[@]}"; do
unset NDD_LOG4B_LEVEL_ANSI_ARGS["$i"]
done
}
# ------------------------------------------------------------------------------
# This is the default profile
ndd::logger::profiles::use_log4j
# ======================================================= public functions =====
# ------------------------------------------------------------------------------
# Log the given message at the given level if active.
# See ndd::logger::log()
#
function log() {
ndd::logger::log "${@}"
}
# ------------------------------------------------------------------------------
# Log the given message at the given level if active.
#
# Globals:
# NDD_LOG4B_LEVEL_VALUES
#
# Arguments:
# @level_name - the logger level to use
# @varargs... - the format and arguments in the 'printf' style
#
# Example:
# log error "This is a %-11s log message" "ERROR"
#
function ndd::logger::log() {
local level_name="${1}"
level_name="$(ndd::logger::_normalize_level "${level_name}")"
level_value=${NDD_LOG4B_LEVEL_VALUES[$level_name]}
ndd::logger::_log_to_stdout "${level_name}" ${level_value} "${@:2}"
ndd::logger::_log_to_file "${level_name}" ${level_value} "${@:2}"
}
# ------------------------------------------------------------------------------
# Conveniently print all the logging levels with their look and feel.
#
# Globals:
# NDD_LOG4B_LEVEL_NAMES
# NDD_LOG4B_LEVEL_VALUES
#
# Arguments:
# None
#
# Outputs:
# Print all the logging levels with their look and feel to stdout
#
function ndd::logger::print_levels() {
if ! command -v ansi::isAnsiSupported > /dev/null; then
echo "Source the 'ansi' library (https://github.com/fidian/ansi/) to add colors!"
fi
for level_name in "${NDD_LOG4B_LEVEL_NAMES[@]}"; do
local level_value="${NDD_LOG4B_LEVEL_VALUES[$level_name]}"
local message
message="$(ndd::logger::_colorize_for_level "${level_name}" " Some text as example ")"
printf "%s %-11s %s\n" "${level_value}" "${level_name}" "${message}"
done
}
# ------------------------------------------------------------------------------
# Set the date format of the file appender.
#
# Globals:
# _NDD_LOG4B_FILE_DATE_FORMAT
#
# Arguments:
# @date_format - the date format to set
#
function ndd::logger::set_file_date_format() {
local date_format="${1}"
_NDD_LOG4B_FILE_DATE_FORMAT="${date_format}"
}
# ------------------------------------------------------------------------------
# Set the level of the file appender. The level name is normalized.
#
# Globals:
# _NDD_LOG4B_FILE_LEVEL
#
# Arguments:
# @level_name - the logger level to set
#
function ndd::logger::set_file_level() {
local level_name="${1}"
_NDD_LOG4B_FILE_LEVEL="$(ndd::logger::_normalize_level "${level_name}")"
}
# ------------------------------------------------------------------------------
# Set the level of the file appender.
#
# Globals:
# _NDD_LOG4B_FILE_LOG_FORMAT
#
# Arguments:
# @log_format - the log format to set
#
function ndd::logger::set_file_log_format() {
local log_format="${1}"
_NDD_LOG4B_FILE_LOG_FORMAT="${log_format}"
}
# ------------------------------------------------------------------------------
# Set the path of the file appender.
#
# Globals:
# _NDD_LOG4B_FILE_PATH
#
# Arguments:
# @log_format - the log format to set
#
function ndd::logger::set_file_path() {
local file_path="${1}"
_NDD_LOG4B_FILE_PATH="${file_path}"
}
# ------------------------------------------------------------------------------
# Set the date format of the stdout appender.
#
# Globals:
# _NDD_LOG4B_STDOUT_DATE_FORMAT
#
# Arguments:
# @date_format - the date format to set
#
function ndd::logger::set_stdout_date_format() {
local date_format="${1}"
_NDD_LOG4B_STDOUT_DATE_FORMAT="${date_format}"
}
# ------------------------------------------------------------------------------
# Set the level of the stdout appender. The level name is normalized.
#
# Globals:
# _NDD_LOG4B_STDOUT_LEVEL
#
# Arguments:
# @level_name - the logger level to set
#
function ndd::logger::set_stdout_level() {
local level_name="${1}"
_NDD_LOG4B_STDOUT_LEVEL="$(ndd::logger::_normalize_level "${level_name}")"
}
# ------------------------------------------------------------------------------
# Set the level of the stdout appender. The level name is normalized.
#
# Globals:
# _NDD_LOG4B_STDOUT_LOG_FORMAT
#
# Arguments:
# @log_format - the log format to set
#
function ndd::logger::set_stdout_log_format() {
local log_format="${1}"
_NDD_LOG4B_STDOUT_LOG_FORMAT="${log_format}"
}
# ====================================================== private functions =====
# ------------------------------------------------------------------------------
# Colorize the given message according to the given level configuration.
# This is a private function.
#
# Globals:
# NDD_LOG4B_LEVEL_ANSI_ARGS
#
# Arguments:
# @level_name - the logger level to use (see NDD_LOG4B_LEVEL_NAMES)
# @message - the message to colorize
#
# Outputs:
# Print the colorized (or not) message to stdout
#
function ndd::logger::_colorize_for_level() {
local level_name="${1}"
local message="${2}"
local ansi_args="${NDD_LOG4B_LEVEL_ANSI_ARGS[$level_name]}"
ndd::logger::_colorize_with_ansi "${ansi_args}" "${message}"
}
# ------------------------------------------------------------------------------
# Colorize the given message according to the given 'ansi' arguments if 'ansi"
# is present and supported.
# This is a private function.
#
# Arguments:
# @ansi_args - the ansi arguments to apply
# @message - the message to colorize
#
# Outputs:
# Print the colorized (or not) message to stdout
#
function ndd::logger::_colorize_with_ansi() {
local ansi_args="${1}"
local message="${2}"
# check if 'ansi' is present and if this is a TTY
if command -v ansi::isAnsiSupported > /dev/null && ansi::isAnsiSupported; then
# shellcheck disable=2086
ansi ${ansi_args} "${message}"
else
echo "${message}"
fi
}
# ------------------------------------------------------------------------------
# Log the given message to a text file at the given level if active.
# This is a private function.
#
# Globals:
# NDD_LOG4B_LEVEL_VALUES
# _NDD_LOG4B_FILE_DATE_FORMAT
# _NDD_LOG4B_FILE_LEVEL
# _NDD_LOG4B_FILE_PATH
#
# Arguments:
# @level_name - the logger level to use
# @level_value - the logger level to use
# @varargs... - the format and arguments in the 'printf' style
#
# Example:
# log error "This is a %-11s log message" "ERROR"
#
function ndd::logger::_log_to_file() {
local level_name="${1}"
local level_value="${2}"
local maximum_level_value=${NDD_LOG4B_LEVEL_VALUES[$_NDD_LOG4B_FILE_LEVEL]}
if [[ "${level_value}" -le ${maximum_level_value} ]]; then
if [[ -z "${_NDD_LOG4B_FILE_PATH}" ]]; then
ndd::logger::_print_error "┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
ndd::logger::_print_error "┃ The output text file is undefined (please set 'NDD_LOG4B_FILE_PATH')"
ndd::logger::_print_error "┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
return 1
fi
local log_date
local log_level_name
local log_message
local log_line
log_date="$(date "${_NDD_LOG4B_FILE_DATE_FORMAT}")"
log_level_name="${NDD_LOG4B_LEVEL_DISPLAY_NAMES[$level_name]}"
# printf chokes on special characters like '-' which is rather annoying
# so we explicitly make the distinction between 'printf' and 'echo' using the number of arguments
if [[ "${#}" -ge 4 ]]; then
# shellcheck disable=2059
log_message="$(printf "${@:3}")"
else
log_message="${*:3}"
fi
# shellcheck disable=2059
log_line="$(printf "${_NDD_LOG4B_FILE_LOG_FORMAT}" "${log_date}" "${log_level_name}" "${log_message}")"
echo -e "${log_line}" >> "${_NDD_LOG4B_FILE_PATH}"
fi
}
# ------------------------------------------------------------------------------
# Log the given message to stdout at the given level if active.
# This is a private function.
#
# Globals:
# NDD_LOG4B_LEVEL_VALUES
# _NDD_LOG4B_STDOUT_DATE_FORMAT
# _NDD_LOG4B_STDOUT_LEVEL
#
# Arguments:
# @level_name - the logger level to use
# @level_value - the logger level to use
# @varargs... - the format and arguments in the 'printf' style
#
# Example:
# log error "This is a %-11s log message" "ERROR"
#
function ndd::logger::_log_to_stdout() {
local level_name="${1}"
local level_value="${2}"
local maximum_level_value=${NDD_LOG4B_LEVEL_VALUES[$_NDD_LOG4B_STDOUT_LEVEL]}
if [[ "${level_value}" -le ${maximum_level_value} ]]; then
local log_date
local log_level_name
local log_message
local log_line
log_date="$(date "${_NDD_LOG4B_STDOUT_DATE_FORMAT}")"
log_level_name="${NDD_LOG4B_LEVEL_DISPLAY_NAMES[$level_name]}"
# printf chokes on special characters like '-' which is rather annoying
# so we explicitly make the distinction between 'printf' and 'echo' using the number of arguments
if [[ "${#}" -ge 4 ]]; then
# shellcheck disable=2059
log_message="$(printf "${@:3}")"
else
log_message="${*:3}"
fi
# shellcheck disable=2059
log_line="$(printf "${_NDD_LOG4B_STDOUT_LOG_FORMAT}" "${log_date}" "${log_level_name}" "${log_message}")"
ndd::logger::_colorize_for_level "${level_name}" "${log_line}"
fi
}
# ------------------------------------------------------------------------------
# Normalize the given logger level name, taking the synonyms into account.
# Print an error message and exit with 1 if the log level cannot be normalized.
# This is a private function.
#
# Globals:
# NDD_LOG4B_LEVEL_SYNONYMS
# NDD_LOG4B_LEVEL_NAMES
#
# Arguments:
# @level_name - the logger level name to use (see NDD_LOG4B_LEVEL_NAMES)
#
# Outputs:
# Print the normalized logger level to stdout
#
function ndd::logger::_normalize_level() {
local level_name="${1}"
level_name="$(ndd::logger::_to_upper "${level_name}")"
# search for a level synonym
for level_synonym in "${!NDD_LOG4B_LEVEL_SYNONYMS[@]}"; do
if [[ "${level_name}" == "${level_synonym}" ]]; then
level_name="${NDD_LOG4B_LEVEL_SYNONYMS[$level_synonym]}"
fi
done
# print DISABLED and return if disabled (because DISABLED is not in NDD_LOG4B_LEVEL_NAMES)
if [[ "${level_name}" == "DISABLED" ]]; then
echo "${level_name}"
return 0
fi
# print the logger level name and return if valid
for valid_level_name in "${NDD_LOG4B_LEVEL_NAMES[@]}"; do
if [[ "${level_name}" == "${valid_level_name}" ]]; then
echo "${level_name}"
return 0
fi
done
# print an error message then exit with 1
ndd::logger::_print_error "┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
ndd::logger::_print_error "┃ Invalid log level: ${level_name}"
ndd::logger::_print_error "┃ Stacktrace:"
local first_trace=0
local stack_depth=${#FUNCNAME[@]}
for ((i=first_trace; i<stack_depth; i++)); do
local function_name="${FUNCNAME[$i]}"
local line_number="${BASH_LINENO[$((i - 1))]}"
local file_path="${BASH_SOURCE[$((i))]}"
ndd::logger::_print_error "┃ in ${function_name} (${file_path}:${line_number})"
done
ndd::logger::_print_error "┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
return 1
}
# ------------------------------------------------------------------------------
# Print the given message to stderr, in red if 'ansi' if present.
# This is a private function.
#
# Arguments:
# @message - the message to print
#
# Outputs:
# Print the colorized (or not) message to stderr
#
function ndd::logger::_print_error() {
local message="${1}"
if command -v ansi::isAnsiSupported > /dev/null && ansi::isAnsiSupported; then
# shellcheck disable=2086
echo -e "$(ansi --bold --red "${message}")" >&2
else
echo -e "${message}" >&2
fi
}
# ------------------------------------------------------------------------------
# Convert the given string to uppercase.
# This is a private function.
#
# Arguments:
# @string - the string to upper case
#
# Outputs:
# Print the uppercase string to stdout
#
function ndd::logger::_to_upper() {
local string="${1}"
echo "${string}" | awk '{print toupper($0)}'
}

View file

@ -0,0 +1 @@
ndd-log4b-0.3.0.sh

1
bin/ndd-utils4b Symbolic link
View file

@ -0,0 +1 @@
ndd-utils4b-0.1.1

View file

@ -0,0 +1,297 @@
#!/usr/bin/env bash
# ==============================================================================
# NDD Utils4B -- Simple utility library for Bash.
#
# Copyright 2020 David DIDIER - All Rights Reserved
# Released under the MIT license (https://opensource.org/licenses/MIT)
#
# Author - David DIDIER
# Repository - https://gitlab.com/ddidier/bash-ndd-utils4b
# Version - 0.1.1
# ------------------------------------------------------------------------------
#
# See https://gitlab.com/ddidier/bash-ndd-utils4b for more details.
#
# ==============================================================================
# Avoid sourcing this library more than one time
if [[ -n "${NDD_UTILS4B_SOURCED+x}" ]] && [[ ${NDD_UTILS4B_SOURCED} ]]; then
return 0
fi
NDD_UTILS4B_SOURCED=true
# ==============================================================================
# Commons
# ==============================================================================
# ------------------------------------------------------------------------------
# Enable some extended error catching.
#
function ndd::base::catch_more_errors_on() {
set -o pipefail # trace ERR through pipes
set -o errtrace # trace ERR through 'time command' and other functions
set -o nounset # set -u : exit the script if you try to use an uninitialised variable
set -o errexit # set -e : exit the script if any statement returns a non-true return value
}
# ------------------------------------------------------------------------------
# Disable some extended error catching.
#
function ndd::base::catch_more_errors_off() {
set +o pipefail # trace ERR through pipes
set +o errtrace # trace ERR through 'time command' and other functions
set +o nounset # set -u : exit the script if you try to use an uninitialised variable
set +o errexit # set -e : exit the script if any statement returns a non-true return value
}
# ------------------------------------------------------------------------------
# Print the stacktrace to stderr with function names, line numbers and file paths.
# If this function is called from another function, use the 'nested_level' argument.
#
# Arguments:
# @nested_level (integer) - the first trace to print (default = O)
#
# Outputs:
# Print the stacktrace to stderr
#
function ndd::base::print_stack_trace() {
local nested_level=${1:-0}
local first_trace=$nested_level
local stack_depth=$(( ${#FUNCNAME[@]} - 1 ))
for ((i=first_trace; i<stack_depth; i++)); do
local function_name="${FUNCNAME[$((i + 1))]}"
local line_number="${BASH_LINENO[$i]}"
local file_path="${BASH_SOURCE[$((i + 1))]}"
echo " in ${function_name} ($(realpath "$file_path"):${line_number})" >&2
done
}
# ==============================================================================
# Strings
# ==============================================================================
# ------------------------------------------------------------------------------
# Convert the given string to lowercase.
#
# Arguments:
# @string - the string to convert
#
# Outputs:
# Print the lowercase string to stdout
#
function ndd::strings::to_lower() {
echo "${1}" | awk '{print tolower($0)}'
}
# ------------------------------------------------------------------------------
# Convert the given string to uppercase.
#
# Arguments:
# @string - the string to convert
#
# Outputs:
# Print the uppercase string to stdout
#
function ndd::strings::to_upper() {
echo "${1}" | awk '{print toupper($0)}'
}
# ==============================================================================
# Symbols
# ==============================================================================
function ndd:symbols::_print() {
[[ -z "${3}" ]] && echo "${1}" || echo "${1}${2}${3}"
}
function ndd:symbols::check_mark() {
ndd:symbols::_print "✔️" " " "${1:-}"
}
function ndd:symbols::cross_mark() {
ndd:symbols::_print "❌" " " "${1:-}"
}
function ndd:symbols::exclamation_mark() {
ndd:symbols::_print "❗" " " "${1:-}"
}
function ndd:symbols::success() {
ndd:symbols::_print "✅" " " "${1:-}"
}
function ndd:symbols::failure() {
ndd:symbols::_print "❌" " " "${1:-}"
}
function ndd:symbols::debug() {
ndd:symbols::_print "🐜" " " "${1:-}"
}
function ndd:symbols::information() {
ndd:symbols::_print "" " " "${1:-}"
}
function ndd:symbols::warning() {
ndd:symbols::_print "⚠️" " " "${1:-}"
}
function ndd:symbols::error() {
ndd:symbols::_print "🔥" " " "${1:-}"
}
function ndd:symbols::fatal() {
ndd:symbols::_print "💥" " " "${1:-}"
}
function ndd:symbols::gear() {
ndd:symbols::_print "⚙️ " " " "${1:-}"
}
# function ndd:symbols::collision() {
# ndd:symbols::_print "💥" " " "${1:-}"
# }
# function ndd:symbols::fire() {
# ndd:symbols::_print "🔥" " " "${1:-}"
# }
# function ndd:symbols::no_entry() {
# ndd:symbols::_print "⛔" " " "${1:-}"
# }
# function ndd:symbols::radioactive() {
# ndd:symbols::_print "☢️" " " "${1:-}"
# }
# ==============================================================================
# Print
# ==============================================================================
# ------------------------------------------------------------------------------
# Print a delimiter marking the beginning of another script output.
#
# Outputs:
# Print a delimiter to stdout
#
function ndd::print::script_output_start() {
echo "▼ ~~~~~ start of output ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ▼"
}
# ------------------------------------------------------------------------------
# Print a delimiter marking the end of another script output.
#
# Outputs:
# Print a delimiter to stdout
#
function ndd::print::script_output_end() {
echo "▲ ~~~~~ end of output ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ▲"
}
# ==============================================================================
# Testing
#
# Requires shunit2 (https://github.com/kward/shunit2/)
#
# See pull request https://github.com/kward/shunit2/pull/115
# ==============================================================================
# ------------------------------------------------------------------------------
# Check that a string is empty.
#
# Arguments:
# @string - the string to check
#
function assertStringIsEmpty() {
assertEquals "" "${1}"
}
# ------------------------------------------------------------------------------
# Check that a string is not empty.
#
# Arguments:
# @string - the string to check
#
function assertStringIsNotEmpty() {
assertNotEquals "" "${1}"
}
# ------------------------------------------------------------------------------
# Check that a file exists.
#
# Arguments:
# @string - the path of the file to check
#
function assertFileExists() {
local file_path="${1}"
if [[ ! -f "${file_path}" ]]; then
fail "Expected the file '${file_path}' to exist, but it does not"
fi
}
# ------------------------------------------------------------------------------
# Check that a file does not exist.
#
# Arguments:
# @string - the path of the file to check
#
function assertFileDoesNotExist() {
local file_path="${1}"
if [[ -f "${file_path}" ]]; then
fail "Expected the file '${file_path}' to not exist, but it does"
fi
}
# ------------------------------------------------------------------------------
# Check that a directory exists.
#
# Arguments:
# @string - the path of the directory to check
#
function assertDirectoryExists() {
local directory_path="${1}"
if [[ ! -d "${directory_path}" ]]; then
fail "Expected the directory '${directory_path}' to exist, but it does not"
fi
}
# ------------------------------------------------------------------------------
# Check that a directory does not exist.
#
# Arguments:
# @string - the path of the directory to check
#
function assertDirectoryDoesNotExist() {
local directory_path="${1}"
if [[ -d "${directory_path}" ]]; then
fail "Expected the directory '${directory_path}' to not exist, but it does"
fi
}
# Used to test multiple sourcing
# shellcheck disable=SC2034
TEST_NDD_UTILS4B_SOURCED=true

View file

@ -0,0 +1 @@
ndd-utils4b-0.1.1.sh

136
bin/package.sh Executable file
View file

@ -0,0 +1,136 @@
#!/usr/bin/env bash
# ------------------------------------------------------------------------------
# Package the Sphinx documentation.
#
# Examples:
# ./package
# ./package --name my-documentation --version 1.2.3
# ------------------------------------------------------------------------------
PROJECT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )"
# shellcheck disable=SC1090
source "${PROJECT_DIR}/bin/shflags/shflags"
# shellcheck disable=SC1090
source "${PROJECT_DIR}/bin/ansi/ansi"
# shellcheck disable=SC1090
source "${PROJECT_DIR}/bin/ndd-log4b/ndd-log4b.sh"
# shellcheck disable=SC1090
source "${PROJECT_DIR}/bin/ndd-utils4b/ndd-utils4b.sh"
# shellcheck disable=SC1090
source "${PROJECT_DIR}/bin/variables.sh"
# disable before shflags
ndd::base::catch_more_errors_off
DEFINE_string "name" "${DDIDIER_SPHINX_PROJECT_NAME}" "The name part of the file name" "n"
DEFINE_string "version" "" "The version part of the file name" "v"
DEFINE_boolean "debug" false "Enable debug mode" "d"
read -r -d '' FLAGS_HELP <<EOF
Package the generated documentation in the archive 'dist/\${name}-\${version}.tar.gz'.
Examples:
./package.sh --name my-documentation --version 1.2.3
EOF
# parse the command-line
FLAGS "$@" || exit $?
eval set -- "${FLAGS_ARGV}"
# enable after shflags
ndd::base::catch_more_errors_on
function main() {
if [[ "${FLAGS_debug}" -eq "${FLAGS_TRUE}" ]]; then
# shellcheck disable=SC2034
ndd::logger::set_stdout_level "DEBUG"
else
# shellcheck disable=SC2034
ndd::logger::set_stdout_level "INFO"
fi
local archive_name="${FLAGS_name}"
if [[ -z "${archive_name}" ]]; then
log error "┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log error "┃ The name part cannot be empty. Please use '-n' or '--name'"
log error "┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
exit 1
fi
local archive_version="${FLAGS_version}"
# if [[ -z "${archive_version}" ]]; then
# log info "No version provided."
# if command -v git &> /dev/null; then
# if [[ -d "${PROJECT_DIR}/.git" ]]; then
# if git -C "${PROJECT_DIR}" diff --quiet &> /dev/null; then
# log info "Git repository does exist. Using commit hash as version."
# archive_version="$(git -C "${PROJECT_DIR}" rev-parse HEAD)"
# else
# log info "Git repository is dirty. Using 'snapshot' as version."
# archive_version="snapshot"
# fi
# else
# log info "Git repository does not exist. Using 'snapshot' as version."
# archive_version="snapshot"
# fi
# else
# log info "Git is not available. Using 'snapshot' as version."
# archive_version="snapshot"
# fi
# fi
if [[ -z "${archive_version}" ]]; then
log info "No version provided. Using 'snapshot' as version."
archive_version="snapshot"
fi
local archive_file_name="${archive_name}-${archive_version}.tar.gz"
local distribution_dir="${PROJECT_DIR}/dist"
# ----------
log info "Packaging documentation in '${distribution_dir}/${archive_file_name}'"
rm -rf "${distribution_dir:?}/"
mkdir "${distribution_dir}/"
cp -r "${PROJECT_DIR}/build/html/" "${distribution_dir}/${archive_name}-${archive_version}/"
local tar_options="cfz"
if [[ "${FLAGS_debug}" -eq "${FLAGS_TRUE}" ]]; then
tar_options="${tar_options}v"
fi
log debug "$(ndd::print::script_output_start)"
tar $tar_options "${distribution_dir}/${archive_file_name}" -C "${distribution_dir}/" "${archive_name}-${archive_version}"
log debug "$(ndd::print::script_output_end)"
log info "┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log info "┃ PACKAGE -- Success! "
log info "┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
}
function error_handler() {
local error_code="$?"
test $error_code == 0 && return;
log error "An unexpected error has occured:\n%s" "$(ndd::base::print_stack_trace 2>&1)"
exit 1
}
trap 'error_handler ${?}' ERR
main "${@}"
exit 0

186
bin/serve.sh Executable file
View file

@ -0,0 +1,186 @@
#!/usr/bin/env bash
# ------------------------------------------------------------------------------
# Run the built-in Sphinx development server. Sphinx will watch the project
# directory and rebuild the documentation when a change is detected. The
# documentation is available at http://localhost:<port> (default port is 8000).
#
# Examples:
# ./serve.sh
# ./serve.sh --name my-documentation --interface 0.0.0.0 --port 9000
# ------------------------------------------------------------------------------
PROJECT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )"
# shellcheck disable=SC1090
source "${PROJECT_DIR}/bin/shflags/shflags"
# shellcheck disable=SC1090
source "${PROJECT_DIR}/bin/ansi/ansi"
# shellcheck disable=SC1090
source "${PROJECT_DIR}/bin/ndd-log4b/ndd-log4b.sh"
# shellcheck disable=SC1090
source "${PROJECT_DIR}/bin/ndd-utils4b/ndd-utils4b.sh"
# shellcheck disable=SC1090
source "${PROJECT_DIR}/bin/variables.sh"
# disable before shflags
ndd::base::catch_more_errors_off
DEFINE_string "name" "${DDIDIER_SPHINX_CONTAINER_NAME}" "The name of the container" "n"
DEFINE_string "interface" "${DDIDIER_SPHINX_CONTAINER_EXPOSED_INTERFACE}" "The network interface on the host machine the container is bound to" "i"
DEFINE_integer "port" "${DDIDIER_SPHINX_CONTAINER_EXPOSED_PORT}" "The port on the host machine the container is bound to" "p"
DEFINE_boolean "debug" false "Enable debug mode" "d"
read -r -d '' FLAGS_HELP <<EOF
Run Sphinx in server mode. Sphinx will watch the project directory and rebuild
the documentation whenever a change is detected. The documentation will
be available at http://localhost:<port>. The default port is ${DDIDIER_SPHINX_CONTAINER_EXPOSED_PORT}.
Examples:
./serve.sh
./serve.sh --name my-documentation --interface 0.0.0.0 --port 9000
EOF
# parse the command-line
FLAGS "$@" || exit $?
eval set -- "${FLAGS_ARGV}"
# enable after shflags
ndd::base::catch_more_errors_on
function main() {
if [[ "${FLAGS_debug}" -eq "${FLAGS_TRUE}" ]]; then
# shellcheck disable=SC2034
ndd::logger::set_stdout_level "DEBUG"
else
# shellcheck disable=SC2034
ndd::logger::set_stdout_level "INFO"
fi
local container_name="${FLAGS_name}"
local exposed_interface="${FLAGS_interface}"
local exposed_port="${FLAGS_port}"
if [[ -z "${container_name}" ]]; then
log error "┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log error "┃ The container name cannot be empty. Please use '-n' or '--name'"
log error "┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
exit 1
fi
if [[ -z "${exposed_interface}" ]]; then
log error "┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log error "┃ The exposed interface cannot be empty. Please use '-i' or '--interface'."
log error "┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
exit 1
fi
if [[ -z "${exposed_port}" ]]; then
log error "┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log error "┃ The exposed port cannot be empty. Please use '-p' or '--port'."
log error "┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
exit 1
fi
local docker_image="ddidier/sphinx-doc:${DDIDIER_SPHINX_IMAGE_VERSION}"
local source_directory="${PROJECT_DIR}"
# Use the terminal if present
# local container_uid="${UID}"
# local container_username="${USER}"
local container_uid
local container_username
container_uid="$(id -u)"
container_username="$(id -u -n)"
if [[ -L "${source_directory}" ]]; then
log warning "The source directory cannot be a symbolic link."
source_directory="$(realpath "${source_directory}")"
fi
log info "┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log info "┃ Serving the Sphinx documentation"
log info "┃"
log info "┃ - using the Docker image: ${docker_image}"
log info "┃ - in the container: ${container_name}"
log info "┃ - as the user: ${container_username}"
log info "┃ - as the user ID: ${container_uid}"
log info "┃ - listening on interface: ${exposed_interface}"
log info "┃ - listening on port: ${exposed_port}"
log info "┃"
log info "┃ This container can usually be terminated with: Control+C"
log info "┃ But if this does not work: docker kill ${container_name}"
log info "┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
# Use the TTY if present
local docker_run_interactive=""
local docker_run_tty=""
if [[ -t 1 ]]; then
docker_run_interactive="-i"
docker_run_tty="-t"
fi
# Ignore files specified in variables.sh
local ignored_files=""
for ignored_file in "${DDIDIER_SPHINX_PROJECT_IGNORED_FILES[@]}"; do
ignored_files="${ignored_files} --ignore \"${ignored_file}\""
done
# echo \
# docker run --rm \
# ${docker_run_interactive} \
# ${docker_run_tty} \
# --name "${container_name}" \
# -e USER_ID="${container_uid}" \
# -e USER_NAME="${container_username}" \
# -p "${exposed_interface}:${exposed_port}:${exposed_port}" \
# -v "${source_directory}":/data \
# "${docker_image}" \
# make --makefile=Makefile-sphinx \
# SPHINXPORT="${exposed_port}" \
# SPHINXIGNORE="${ignored_files}" \
# livehtml "$@" \
# || true
log debug "$(ndd::print::script_output_start)"
docker run --rm \
${docker_run_interactive} \
${docker_run_tty} \
--name "${container_name}" \
-e USER_ID="${container_uid}" \
-e USER_NAME="${container_username}" \
-p "${exposed_interface}:${exposed_port}:${exposed_port}" \
-v "${source_directory}":/data \
"${docker_image}" \
make --makefile=Makefile-sphinx \
SPHINXPORT="${exposed_port}" \
SPHINXIGNORE="${ignored_files}" \
livehtml "$@" \
|| true
log debug "$(ndd::print::script_output_end)"
log info " ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log info " ┃ BUILD -- Success! "
log info " ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
}
function error_handler() {
local error_code="$?"
test $error_code == 0 && return;
log error "An unexpected error has occured:\n%s" "$(ndd::base::print_stack_trace 2>&1)"
exit 1
}
trap 'error_handler ${?}' ERR
main "${@}"
exit 0

1
bin/shflags Symbolic link
View file

@ -0,0 +1 @@
shflags-v1.2.3

1206
bin/shflags-v1.2.3/shflags Normal file

File diff suppressed because it is too large Load diff

154
bin/tidy.sh Executable file
View file

@ -0,0 +1,154 @@
#!/usr/bin/env bash
# ------------------------------------------------------------------------------
# Tidy source files in order to be compatible with Sphinx:
# - rename image files with incompatible characters
#
# Examples:
# ./tidy.sh
# ./tidy.sh --debug
# ------------------------------------------------------------------------------
PROJECT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )"
# shellcheck disable=SC1090
source "${PROJECT_DIR}/bin/shflags/shflags"
# shellcheck disable=SC1090
source "${PROJECT_DIR}/bin/ansi/ansi"
# shellcheck disable=SC1090
source "${PROJECT_DIR}/bin/ndd-log4b/ndd-log4b.sh"
# shellcheck disable=SC1090
source "${PROJECT_DIR}/bin/ndd-utils4b/ndd-utils4b.sh"
# shellcheck disable=SC1090
source "${PROJECT_DIR}/bin/variables.sh"
# disable before shflags
ndd::base::catch_more_errors_off
DEFINE_boolean "debug" false "Enable debug mode" "d"
read -r -d '' FLAGS_HELP <<EOF
Tidy source files in order to be compatible with Sphinx:
- rename image files with incompatible characters
Examples:
./tidy.sh
EOF
# parse the command-line
FLAGS "$@" || exit $?
eval set -- "${FLAGS_ARGV}"
# enable after shflags
ndd::base::catch_more_errors_on
#
# TODO extract to ndd-utils library
#
# ------------------------------------------------------------------------------
# Join the given array of string to a single string using the given separator.
#
# Arguments:
# @separator (string) - the separator
# @strings ([string]) - the array of strings to join
#
# Outputs:
# Print the joined string to stdout
#
function ndd::strings::join_by() {
local IFS="${1}"
shift
echo "$*"
}
function main() {
if [[ "${FLAGS_debug}" -eq "${FLAGS_TRUE}" ]]; then
# shellcheck disable=SC2034
ndd::logger::set_stdout_level "DEBUG"
else
# shellcheck disable=SC2034
ndd::logger::set_stdout_level "INFO"
fi
local source_dir="${PROJECT_DIR}/source"
local file_extensions=(bmp gif ico jpg jpeg png tiff js html)
log info "Renaming images"
log info "- in directory '${source_dir}'"
log info "- with extensions $(ndd::strings::join_by "," "${file_extensions[@]}")"
local file_extensions_as_regex
file_extensions_as_regex=$(ndd::strings::join_by "|" "${file_extensions[@]}")
readarray -d '' file_paths < <(\
find "${PROJECT_DIR}/source" \
-regextype posix-extended -regex "^.+\\.(${file_extensions_as_regex})$" \
-print0 \
)
log info "Found ${#file_paths[@]} image file(s) to check"
local renamed_files_count=0
for file_path in "${file_paths[@]}"; do
log debug "- evaluating ${file_path}"
local file_name
local file_directory
local new_file_name
local new_file_path
file_name="$(basename "${file_path}")"
file_directory="$(dirname "${file_path}")"
new_file_name=$( \
echo "${file_name}" \
| sed -r \
-e 's/ /_/g' \
-e 's/\[//g' \
-e 's/\]//g' \
-e 's/[àâä]/a/g' \
-e 's/[éèêë]/e/g' \
-e 's/[îï]/i/g' \
-e 's/[ôö]/o/g' \
-e 's/[ûü]/u/g' \
)
new_file_path="${file_directory}/${new_file_name}"
if [[ "${new_file_name}" == "${file_name}" ]]; then
log debug " - the file name is valid"
else
renamed_files_count=$((renamed_files_count + 1))
log debug " - the file name is invalid"
log debug " renaming '${file_path}'"
log debug " to '${new_file_path}'"
mv "${file_path}" "${new_file_path}"
fi
done
log info "Renamed ${renamed_files_count} image file(s)"
}
function error_handler() {
local error_code="$?"
test $error_code == 0 && return;
log error "An unexpected error has occured:\n%s" "$(ndd::base::print_stack_trace 2>&1)"
exit 1
}
trap 'error_handler ${?}' ERR
main "${@}"
exit 0

38
bin/variables.sh Normal file
View file

@ -0,0 +1,38 @@
#!/usr/bin/env bash
# ------------------------------------------------------------------------------
# This file is sourced by the scripts in the same directory.
# ------------------------------------------------------------------------------
PROJECT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )"
# The name of the project
# shellcheck disable=SC2155
export DDIDIER_SPHINX_PROJECT_NAME="$(basename "${PROJECT_DIR}")"
# The files Sphinx Live HTML must ignore
export DDIDIER_SPHINX_PROJECT_IGNORED_FILES=(
"*.bak"
"*.tmp"
)
# The version of the Docker image ddidier/sphinx-doc
export DDIDIER_SPHINX_IMAGE_VERSION="4.1.2-1"
# The name of the container Sphinx is running in
export DDIDIER_SPHINX_CONTAINER_NAME="${DDIDIER_SPHINX_PROJECT_NAME}"
# The network interface on the host machine the container is bound to
export DDIDIER_SPHINX_CONTAINER_EXPOSED_INTERFACE=127.0.0.1
# The port on the host machine the container is listening to
export DDIDIER_SPHINX_CONTAINER_EXPOSED_PORT=8000
# Generated by ddidier/sphinx-doc
# See https://hub.docker.com/r/ddidier/sphinx-doc
# Docker image commit: 8e920a5e2e849c4ca2248afbbb9215235929c052
# Docker image tag: 4.1.2-1