diff --git a/tools/generate_source_docs.sh b/tools/generate_source_docs.sh
new file mode 100755
index 0000000000000000000000000000000000000000..706fe8220de68af6d9ff58e902fba581fb280db2
--- /dev/null
+++ b/tools/generate_source_docs.sh
@@ -0,0 +1,777 @@
+#!/usr/bin/env bash
+# """Generate mkdocs source code references documentation for bash scripts
+#
+# SYNOPSIS:
+#   `./generate_source_docs.sh [options]`
+#
+# DESCRIPTION:
+#   From the list of nodes stored in `${NODE_LIST[@]}` array in the script,
+#   parse every scripts in nodes and folder nodes to generate their
+#   corresponding references source code documentation for mkdocs and output this
+#   documentation in their corresponding file in the `docs` folder.
+#
+# OPTIONS:
+#
+#   - `-d,--dry-run` : Specify the generation of the documentation is only for
+#                      test purpose:
+#
+# """
+
+# Input folder/script
+NODE_LIST=(
+  "."
+  "tools"
+)
+
+DRY_RUN="false"
+
+SCRIPT_PATH="$( cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 || return 1 ; pwd -P )"
+SCRIPT_FULL_PATH="${SCRIPT_PATH}/$(basename "${BASH_SOURCE[0]}")"
+
+MKDOCS_ROOT="${SCRIPT_PATH//\/tools/}"
+MKDOCS_DEBUG_LEVEL="INFO"
+
+manpage()
+{
+  # """Extract the script documentation from header and print it on stdout
+  #
+  # Simply extract the docstring from the header of the script, format it with
+  # some output enhancement (such as bold) and print it to stdout.
+  #
+  # Globals:
+  #   SCRIPTPATH
+  #
+  # Arguments:
+  #   None
+  #
+  # Output:
+  #   Help to stdout
+  #
+  # Returns:
+  #   None
+  #
+  # """
+
+  local e_normal="\\\e[0m"     # Normal (usually white fg & transparent bg)
+  local e_bold="\\\e[1m"       # Bold
+  # Extract module documentation and format it
+  help_content="$(\
+    sed -n -e "/^# \"\"\".*/,/^# \"\"\"/"p "${SCRIPT_FULL_PATH}" \
+      | sed -e "s/^# \"\"\"//g" \
+            -e "s/^# //g" \
+            -e "s/^#$//g" \
+            -e "s/DESCRIPTION[:]/${e_bold}DESCRIPTION${e_normal}\n/g" \
+            -e "s/COMMANDS[:]/${e_bold}COMMANDS${e_normal}\n/g" \
+            -e "s/OPTIONS[:]/${e_bold}OPTIONS${e_normal}\n/g" \
+            -e "s/SYNOPSIS[:]/${e_bold}SYNOPSIS${e_normal}\n/g")"
+  echo -e "${help_content}"
+  exit 0
+}
+
+
+# - SC2034: var appears unused, Verify use (or export if used externally)
+# shellcheck disable=SC2034
+mkdocs_log()
+{
+  # """Print debug message in colors depending on message severity on stderr
+  #
+  # Echo colored log depending on user provided message severity. Message
+  # severity are associated to following color output:
+  #
+  #   - `DEBUG` print in the fifth colors of the terminal (usually magenta)
+  #   - `INFO` print in the second colors of the terminal (usually green)
+  #   - `WARNING` print in the third colors of the terminal (usually yellow)
+  #   - `ERROR` print in the third colors of the terminal (usually red)
+  #
+  # If no message severity is provided, severity will automatically be set to
+  # INFO.
+  #
+  # Globals:
+  #   ZSH_VERSION
+  #
+  # Arguments:
+  #   $1: string, message severity or message content
+  #   $@: string, message content
+  #
+  # Output:
+  #   Log informations colored
+  #
+  # Returns:
+  #   None
+  #
+  # """
+
+  # Store color prefixes in variable to ease their use.
+  # Base on only 8 colors to ensure portability of color when in tty
+  local e_normal="\e[0m"     # Normal (usually white fg & transparent bg)
+  local e_bold="\e[1m"       # Bold
+  local e_underline="\e[4m"  # Underline
+  local e_debug="\e[0;35m"   # Fifth term color (usually magenta fg)
+  local e_info="\e[0;32m"    # Second term color (usually green fg)
+  local e_warning="\e[0;33m" # Third term color (usually yellow fg)
+  local e_error="\e[0;31m"   # First term color (usually red fg)
+
+  # Store preformated colored prefix for log message
+  local error="${e_bold}${e_error}[ERROR]${e_normal}${e_error}"
+  local warning="${e_bold}${e_warning}[WARNING]${e_normal}${e_warning}"
+  local info="${e_bold}${e_info}[INFO]${e_normal}${e_info}"
+  local debug="${e_bold}${e_debug}[DEBUG]${e_normal}${e_debug}"
+
+  local color_output="e_error"
+  local msg_severity
+  local msg
+
+  # Not using ${1^^} to ensure portability when using ZSH
+  msg_severity=$(echo "$1" | tr '[:upper:]' '[:lower:]')
+
+  if [[ "${msg_severity}" =~ ^(error|time|warning|info|debug)$ ]]
+  then
+    # Shift arguments by one such that $@ start from the second arguments
+    shift
+    # Place the content of variable which name is defined by ${msg_severity}
+    # For instance, if `msg_severity` is INFO, then `prefix` will have the same
+    # value as variable `info`.
+    if [[ -n "${ZSH_VERSION}" ]]
+    then
+      prefix="${(P)msg_severity}"
+    else
+      prefix="${!msg_severity}"
+    fi
+    color_output="e_${msg_severity}"
+  else
+    prefix="${info}"
+  fi
+
+  if [[ -n "${ZSH_VERSION}" ]]
+  then
+    color_output="${(P)color_output}"
+  else
+    color_output="${!color_output}"
+  fi
+
+  # Concat all remaining arguments in the message content and apply markdown
+  # like syntax.
+  msg_content=$(echo "$*" | sed -e "s/ \*\*/ \\${e_bold}/g" \
+                              -e "s/\*\*\./\\${e_normal}\\${color_output}./g" \
+                              -e "s/\*\* /\\${e_normal}\\${color_output} /g" \
+                              -e "s/ \_\_/ \\${e_underline}/g" \
+                              -e "s/\_\_\./\\${e_normal}\\${color_output}./g" \
+                              -e "s/\_\_ /\\${e_normal}\\${color_output} /g")
+  msg="${prefix} ${msg_content}${e_normal}"
+
+  # Print message or not depending on message severity and MKDOCS_DEBUG_LEVEL
+  if [[ -z "${MKDOCS_DEBUG_LEVEL}" ]] && [[ "${msg_severity}" == "error" ]]
+  then
+    echo -e "${msg}" 1>&2
+  elif [[ -n "${MKDOCS_DEBUG_LEVEL}" ]]
+  then
+    case ${MKDOCS_DEBUG_LEVEL} in
+      DEBUG)
+        echo "${msg_severity}" \
+          | grep -q -E "(debug|info|warning|error)" && echo -e "${msg}" 1>&2
+        ;;
+      INFO)
+        echo "${msg_severity}" \
+          | grep -q -E "(info|warning|error)" && echo -e "${msg}" 1>&2
+        ;;
+      WARNING)
+        echo "${msg_severity}" \
+          | grep -q -E "(warning|error)" && echo -e "${msg}" 1>&2
+        ;;
+      ERROR)
+        echo "${msg_severity}" \
+          | grep -q -E "error" && echo -e "${msg}" 1>&2
+        ;;
+    esac
+  fi
+}
+
+
+parse_main_doc()
+{
+  # """Process the content of the main part of the docstring
+  #
+  # Render the mkdocs documentation of the main part of the docstring.
+  #
+  # Globals:
+  #   None
+  #
+  # Arguments:
+  #   None
+  #
+  # Output:
+  #   Render content of the main parts of the docstring on stdout
+  #
+  # Returns:
+  #   None
+  #
+  # """
+
+  if [[ -n "${main_doc}" ]]
+  then
+    while IFS= read -r i_line
+    do
+      echo "${quote_indent} ${i_line/${space_indent}}"
+    done <<< "$(echo -e "${main_doc}")"
+    echo "${quote_indent}"
+  fi
+}
+
+parse_globals_doc()
+{
+  # """Process the content of the globals part of the docstring
+  #
+  # If `Globals` part of the docstring is not `None`, render the mkdocs
+  # documentation.
+  #
+  # Globals:
+  #   None
+  #
+  # Arguments:
+  #   None
+  #
+  # Output:
+  #   Render content of the globals parts of the docstring on stdout
+  #
+  # Returns:
+  #   None
+  #
+  # """
+
+  if [[ -n "${globals_doc}" ]] && ! [[ "${globals_doc}" =~ "None" ]]
+  then
+    echo -e "${quote_indent} **Globals**"
+    echo "${quote_indent}"
+    # `IFS=` here is local to the loop and make the read do not hide leading
+    # space to keep indentation of the current line.
+    while IFS= read -r i_line
+    do
+      # If line is not empty
+      if [[ -n "${i_line}" ]] && ! [[ "${i_line}" =~ ^[[:space:]]*$ ]]
+      then
+        echo "${quote_indent} - \`${i_line/${space_indent}}\`"
+      fi
+    done <<< "$(echo -e "${globals_doc}")"
+  fi
+  echo "${quote_indent}"
+}
+
+parse_arguments_doc()
+{
+
+  # """Process the content of the arguments part of the docstring
+  #
+  # If `Arguments` part of the docstring is not `None`, render the mkdocs
+  # documentation.
+  #
+  # Globals:
+  #   None
+  #
+  # Arguments:
+  #   None
+  #
+  # Output:
+  #   Render content of the arguments parts of the docstring on stdout
+  #
+  # Returns:
+  #   None
+  #
+  # """
+
+  local argument
+  local description
+  local line_content
+
+  if [[ -n "${arguments_doc}" ]] && ! [[ "${arguments_doc}" =~ "None" ]]
+  then
+    # `IFS=` here is local to the loop and make the read do not hide leading
+    # space to keep indentation of the current line.
+    echo "${quote_indent} **Arguments**"
+    echo "${quote_indent}"
+    echo "${quote_indent} | Arguments | Description |"
+    echo "${quote_indent} | :-------- | :---------- |"
+    while IFS= read -r i_line
+    do
+      # If line is not empty
+      if [[ -n "${i_line}" ]] && ! [[ "${i_line}" =~ ^[[:space:]]*$ ]]
+      then
+        line_content="${i_line/${space_indent}}"
+        argument="\`${line_content%%:*}\`"
+        description="${line_content##*:}"
+        echo -e "${quote_indent} | ${argument} | ${description} |"
+      fi
+    done <<< "$(echo -e "${arguments_doc}")"
+    echo "${quote_indent}"
+  fi
+}
+
+parse_output_doc()
+{
+  # """Process the content of the output part of the docstring
+  #
+  # If `Output` part of the docstring is not `None`, render the mkdocs
+  # documentation.
+  #
+  # Globals:
+  #   None
+  #
+  # Arguments:
+  #   None
+  #
+  # Output:
+  #   Render content of the return parts of the docstring on stdout
+  #
+  # Returns:
+  #   None
+  #
+  # """
+
+  if [[ -n "${output_doc}" ]] && ! [[ "${output_doc}" =~ "None" ]]
+  then
+    echo -e "${quote_indent} **Output**"
+    echo "${quote_indent}"
+    # `IFS=` here is local to the loop and make the read do not hide leading
+    # space to keep indentation of the current line.
+    while IFS= read -r i_line
+    do
+      # If current line is not empty
+      if [[ -n "${i_line}" ]] && ! [[ "${i_line}" =~ ^[[:space:]]*$ ]]
+      then
+        echo "${quote_indent} - ${i_line/${space_indent}}"
+      fi
+    done <<< "$(echo -e "${output_doc}")"
+    echo "${quote_indent}"
+  fi
+}
+
+parse_returns_doc()
+{
+  # """Process the content of the return part of the docstring
+  #
+  # If `Returns` part of the docstring is not `None`, render the mkdocs
+  # documentation.
+  #
+  # Globals:
+  #   None
+  #
+  # Arguments:
+  #   None
+  #
+  # Output:
+  #   Rendered content of the return parts of the docstring on stdout
+  #
+  # Returns:
+  #   None
+  #
+  # """
+
+  if [[ -n "${returns_doc}" ]] && ! [[ "${returns_doc}" =~ "None" ]]
+  then
+    echo "${quote_indent} **Returns**"
+    echo "${quote_indent}"
+    # `IFS=` here is local to the loop and make the read do not hide leading
+    # space to keep indentation of the current line.
+    while IFS= read -r i_line
+    do
+      # If current line is not empty
+      if [[ -n "${i_line}" ]] && ! [[ "${i_line}" =~ ^[[:space:]]*$ ]]
+      then
+        echo -e "${quote_indent} - ${i_line/${space_indent}}"
+      fi
+    done <<< "$(echo -e "${returns_doc}")"
+    echo "${quote_indent}"
+  fi
+}
+
+parse_method_doc_line()
+{
+  # """Process current line of the method documentation
+  #
+  # For the current line of the method docstring (value of `${i_line}` sets in
+  # the parent method), add its content to the variable storing part of the
+  # documentation to later be processed.
+  #
+  # Globals:
+  #   MKDOCS_ROOT
+  #
+  # Arguments:
+  #   None
+  #
+  # Output:
+  #   Render content of the header of the docstring on stdout
+  #   Warning log if optional part of the docstring are missing on stderr
+  #   Error log if required part of the docstring are missing on stderr
+  #
+  # Returns:
+  #   1 if required part of the docstring are missing
+  #
+  # """
+
+  # If parsing first line of the docstring, i.e. the header
+  if [[ "${part}" == "header" ]]
+  then
+    if ! [[ "${i_line}" =~ \"+[A-Za-z] ]]
+    then
+      mkdocs_log "ERROR" "Mehod **${method_name}** in" \
+        "**${i_node//${MKDOCS_ROOT}\/}** does not have **header** description."
+      return 1
+    else
+      echo "${quote_indent} **${i_line//${header_regexp_delete}}**"
+    fi
+    part="main"
+  # If current line define a new part (except `main`)
+  elif [[ "${i_line}" =~ (Globals|Arguments|Output|Returns): ]]
+  then
+    # Get the name of the variable storing the current part of the docstring
+    var_subst="$( echo ${part} | tr '[:upper:]' '[:lower:]')_doc"
+
+    # Handling of zsh for variable substitution
+    if [[ -n "${ZSH_VERSION}" ]]
+    then
+      part_content="${(P)var_subst}"
+    else
+      part_content="${!var_subst}"
+    fi
+
+    # If part content is empty or made of only empty lines
+    if [[ -z "${part_content}" ]] || [[ -z "$(echo -e "${part_content}")" ]]
+    then
+      if [[ "${part}" == "main" ]]
+      then
+        mkdocs_log "WARNING" \
+          "Method **${method_name}** in **${i_node//${MKDOCS_ROOT}\/}**" \
+          "does not have **${part}** description."
+      else
+        mkdocs_log "ERROR" \
+          "Method **${method_name}** in **${i_node//${MKDOCS_ROOT}\/}**" \
+          "does not have **${part}** description."
+        return 1
+      fi
+    fi
+
+    # Normally, when changing part, comment of part should have two more space
+    # than the main part of the docstring.
+    if [[ "${part}" == "main" ]]
+    then
+      space_indent+="  "
+    fi
+
+    # Update the current part name
+    part=$(echo "${i_line}" | sed -e "s/^ *//g" -e "s/:$//g")
+  else
+    # Add line to the variable corresponding to the currently parsed docstring
+    # part.
+    case "${part}" in
+      main)
+        main_doc+="${i_line/${space_indent}}\n"
+        ;;
+      Globals)
+        globals_doc+="${i_line}\n"
+        ;;
+      Arguments)
+        arguments_doc+="${i_line}\n"
+        ;;
+      Output)
+        output_doc+="${i_line}\n"
+        ;;
+      Returns)
+        returns_doc+="${i_line}\n"
+        ;;
+    esac
+  fi
+}
+
+generate_method_docs()
+{
+  # """Generate mkdocs documentation from a method docstring
+  #
+  # For the method name with its docstring passed as first argument, parse it
+  # content and add it to the script documentation.
+  #
+  # Globals:
+  #   None
+  #
+  # Arguments:
+  #   $1: string, method name with its docstring
+  #
+  # Output:
+  #   Rendered documentation on stdout
+  #   Error log if required part of the docstring are missing on stderr
+  #
+  # Returns:
+  #   1 if required part of the docstring are missing
+  #
+  # """
+
+  # Content of the docstring
+  local method_doc="$1"
+
+  # First part of the docstring
+  local header_regexp_delete=' *"""'
+  local method_name
+  local method_full_desc
+
+  # Variable storing subpart of the docstring
+  local part="header"
+  local part_content=""
+  local var_subst=""
+
+  # Variable storing documentation of each part of the docstring
+  local main_doc=""
+  local globals_doc=""
+  local arguments_doc=""
+  local output_doc=""
+  local returns_doc=""
+
+  # Default markdown title depth
+  local toc_depth="##"
+
+  # Extract the method name
+  method_name="$(grep -E ".*\(\)$" <<<"${method_doc}" | sed "s/^ *//g")"
+
+  # Extract only the docstring without the comment prefix `#`
+  # - SC2026: This word (`p`) is outside of quotes
+  # shellcheck disable=SC2026
+  method_full_desc=$(echo "${method_doc}" \
+    | sed -n -e '/# """.*/,/# """/'p \
+    | sed -e 's/# //g' \
+          -e 's/"""$//g' \
+          -e 's/#$//g' \
+  )
+
+  # Compute TOC depth of the method
+  if [[ "${nb_indent}" -ne 0 ]]
+  then
+    toc_depth+="$(printf "%$(( nb_indent ))s" '#')"
+  fi
+
+  # Output title of the method name with its depth
+  echo -e "\n\n${toc_depth} ${method_name}\n"
+
+  # Normally, indentation of docstring should be two more space that method
+  # indentation.
+  space_indent+="  "
+
+  # `IFS=` here is local to the loop and make the read do not hide leading space
+  # to keep indentation of the current line.
+  # - SC2116: Useless echo ?
+  # shellcheck disable=SC2116
+  while IFS= read -r i_line
+  do
+    parse_method_doc_line
+  done <<<"$(echo "${method_full_desc}")"
+
+  # Remove indentation correction
+  space_indent=${space_indent:-4}
+
+  # Process the aggregated documentation per parts
+  parse_main_doc
+  parse_globals_doc
+  parse_arguments_doc
+  parse_output_doc
+  parse_returns_doc
+  echo "${quote_indent}"
+}
+
+generate_doc()
+{
+  # """Generate mkdocs documentation of the current node
+  #
+  # For the current node (value of `${i_node}` set in parent method), extract
+  # the main script documentation, then extract every method name and for every
+  # method name, call the method to parse their documentation.
+  # Finally, print the generate documentation in it corresponding file in `docs`
+  # folder.
+  #
+  # Globals:
+  #   MKDOCS_ROOT
+  #
+  # Arguments:
+  #   None
+  #
+  # Output:
+  #   Error log if script does not have main documentation
+  #
+  # Returns:
+  #   1 if script does not have main documentation
+  #
+  # """
+
+  local output_file=${i_node}
+  local space_indent
+  local quote_indent
+  local nb_indent
+  local script_doc
+  local full_doc
+
+  # Handle files starting with `.` like `.envrc`
+  if [[ "${i_node}" =~ ^\. ]]
+  then
+    output_file="${i_node/.}"
+  fi
+  output_file="${MKDOCS_ROOT}/docs/references/${output_file//.sh}.md"
+
+  # Extract module documentation
+  script_doc="$(sed -n -e "/^# \"\"\".*/,/^# \"\"\"/"p "${i_node}" \
+                | sed -e "s/^# \"\"\"//g" \
+                      -e "s/^# //g" \
+                      -e "s/^  //g" \
+                      -e "s/^#$//g" \
+                      -e "s/DESCRIPTION[:]/## Description\n/g" \
+                      -e "s/COMMANDS[:]/## Commands\n/g" \
+                      -e "s/OPTIONS[:]/## Options\n/g" \
+                      -e "s/SYNOPSIS[:]/## Synopsis\n/g" \
+  )"
+
+  if [[ -z ${script_doc} ]]
+  then
+    mkdocs_log "ERROR" "Script **${i_node}** does not have documentation."
+    return 1
+  fi
+
+  # Build directory in documentation folder respecting the tree structure of the
+  # `i_node` currently parsed.
+  if [[ "${DRY_RUN}" == "false" ]]
+  then
+    mkdir -p "${MKDOCS_ROOT}/docs/references/$(dirname "${i_node}")"
+  fi
+
+  # Start building the complete documentation
+  full_doc="# $(basename "${i_node}")\n\n"
+  full_doc+="${script_doc}\n\n"
+
+  # For every method_name, `IFS=` here is local to the loop and make the read
+  # do not hide leading space to keep indentation of the current method name.
+  while IFS= read -r i_method_name
+  do
+    # Determine the number of space indentation
+    space_indent=${i_method_name%%[a-z]*}
+    nb_indent=$(( ${#space_indent} / 2 ))
+    if [[ "${nb_indent}" -ne 0 ]]
+    then
+      quote_indent="$(printf "%${nb_indent}s" ">")"
+      method_content=$(sed -n -e "/${i_method_name}/,/# \"\"\"$/"p "${i_node}")
+    else
+      quote_indent=""
+      method_content=$(sed -n -e "/^${i_method_name}/,/# \"\"\"$/"p "${i_node}")
+    fi
+    full_doc+="$(generate_method_docs "${method_content}")"
+  done <<<"$(grep -E '[a-zA-Z_]\(\)' "${i_node}")"
+
+  if [[ "${DRY_RUN}" == "false" ]]
+  then
+    echo -e "${full_doc}" > "${output_file}"
+  fi
+}
+
+build_doc()
+{
+  # """Recursive method that call the documentation builder for every file
+  #
+  # For every node provided as arguments, if node is a file, then process its
+  # documentation build. Else, if node is a folder, add all `*.sh` file in this
+  # folder to a temporary array which later is passed recursively as arguments to
+  # this method.
+  #
+  # Globals:
+  #   MKDOCS_ROOT
+  #
+  # Arguments:
+  #   $1: Bash array, List of node (files or folder) which documentation should be built.
+  #
+  # Output:
+  #   Information log to tell which node is currently computed.
+  #   Warning log to when node does not exist.
+  #
+  # Returns:
+  #   None
+  #
+  # """
+  local abs_path
+  local i_node
+  local tmp_nodes=()
+
+  for i_node in "$@"
+  do
+    # Build absolute path of the node
+    abs_path="${MKDOCS_ROOT}/${i_node}"
+
+    if [[ -f "${abs_path}" ]]
+    then
+      mkdocs_log "INFO" "Computing documentation of **${i_node}**."
+      generate_doc || error="true"
+    elif [[ -d "${abs_path}" ]]
+    then
+      for i_subnode in "${abs_path}"/*.sh
+      do
+        # Handle folder where there is not `*.sh` file
+        if [[ "${i_subnode}" != "${abs_path}/*.sh" ]]
+        then
+          # Remove every occurrences of `${MKDOCS_ROOT}`
+          i_subnode="${i_subnode//${MKDOCS_ROOT}\//}"
+          tmp_nodes+=("${i_subnode}")
+        fi
+      done
+    else
+      mkdocs_log "WARNING" "Node **${i_node}** does not exists !"
+    fi
+  done
+
+  # Call this method for subnode
+  if [[ -n "${tmp_nodes[*]}" ]]
+  then
+    build_doc "${tmp_nodes[@]}" || error="true"
+  fi
+
+  if [[ "${error}" == "true" ]]
+  then
+    return 1
+  fi
+  return 0
+}
+
+main()
+{
+  # """Main method that build source documentat for every files
+  #
+  # First ensure that directory environment is activated first, then load
+  # libraries script and finally call the building doc methods.
+  #
+  # Globals:
+  #   MKDOCS_ROOT
+  #   NODE_LIST
+  #
+  # Arguments:
+  #   None
+  #
+  # Output:
+  #   Error log if directory environment is not activated yet
+  #
+  # Returns:
+  #   1 if directory environment is not activated yet
+  #
+  # """
+
+  while [[ $# -gt 0 ]]
+  do
+    case $1 in
+      -d|--dry-run)
+        DRY_RUN="true"
+        shift
+        ;;
+      --help|-h)
+        manpage
+        ;;
+    esac
+  done
+  cd "${MKDOCS_ROOT}" || return 1
+
+  build_doc "${NODE_LIST[@]}" || return 1
+}
+
+main "$@"
+
+# ------------------------------------------------------------------------------
+# VIM MODELINE
+# vim: ft=bash: foldmethod=indent
+# ------------------------------------------------------------------------------