Files
projdump/projdump.sh
Кокос Артем Николаевич 7a51403a6a Use Markdown in output
2026-02-12 12:26:01 +07:00

117 lines
3.8 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# projdump.sh - dump project structure and source code into a single Markdown file
set -euo pipefail
usage() {
cat >&2 <<EOF
Использование: $0 <директория>
Создаёт один файл:
<basename>-dump.md — дерево проекта + содержимое файлов в Markdown
Игнорирует типичные артефакты сборки, кэши, IDE-файлы и зависимости.
Параметры:
-h, --help Показать эту справку
EOF
}
if [[ $# -eq 0 ]] || [[ "$1" == "-h" ]] || [[ "$1" == "--help" ]]; then
usage
exit 0
fi
TARGET_DIR="$1"
if [[ ! -d "$TARGET_DIR" ]]; then
echo "Ошибка: директория '$TARGET_DIR' не существует." >&2
exit 1
fi
TARGET_DIR="$(cd "$TARGET_DIR" && pwd)"
BASENAME=$(basename "$TARGET_DIR")
if ! command -v tree >/dev/null 2>&1; then
echo "Ошибка: требуется утилита 'tree'. Установите её (например, apt install tree)." >&2
exit 1
fi
IGNORE_LIST=(
"third_party" "3rd_party" "3rdparty" ".git" ".svn" ".hg" "node_modules"
"__pycache__" "*.pyc" ".venv" "venv" "env" ".env" ".idea" ".vscode" ".vs"
".DS_Store" "Thumbs.db" "dist" "build" "out" "target" ".pytest_cache"
".mypy_cache" ".next" ".nuxt" ".output" ".svelte-kit" "coverage" ".cache"
".parcel-cache" ".eslintcache" ".yarn" "yarn-error.log" "package-lock.json"
"yarn.lock" "pnpm-lock.yaml" "Cargo.lock" "go.sum" ".gradle" "gradle"
".mvn" "mvnw" "mvnw.cmd" "*.swp" "*.swo" ".stack-work" "_build" "deps"
".cargo" ".rustup" ".clangd" ".ccls-cache" "CMakeFiles" "CMakeCache.txt"
"CTestTestfile.cmake" "cmake_install.cmake" "*.dSYM" "*.ilk" "*.pdb"
"*.obj" "*.o" "*.so" "*.dylib" "*.dll" "*.exe" "*.bin" "*.hex" "*.elf"
"tags" "TAGS" "GPATH" "GTAGS" "GRTAGS" "GSYMS" ".github" ".gitlab"
".circleci" ".travis.yml" "Jenkinsfile" "Dockerfile*" "docker-compose*.yml"
"*.log" "logs" "tmp" "temp" ".terraform" ".tfstate" ".tfstate.backup" "*.tfvars"
)
# === Подготовка find-аргументов ===
FIND_IGNORE_ARGS=()
for pat in "${IGNORE_LIST[@]}"; do
if [[ "$pat" == */* ]]; then
FIND_IGNORE_ARGS+=(-o -path "*/$pat")
else
FIND_IGNORE_ARGS+=(-o -name "$pat")
fi
done
FIND_CMD=(find "$TARGET_DIR" \( -false "${FIND_IGNORE_ARGS[@]}" \) -prune -o -type f -print0)
# === Подготовка шаблонов для tree ===
TREE_IGNORE_PATTERNS=""
for pat in "${IGNORE_LIST[@]}"; do
base_pat="${pat%%/*}"
if [[ -z "$TREE_IGNORE_PATTERNS" ]]; then
TREE_IGNORE_PATTERNS="$base_pat"
else
TREE_IGNORE_PATTERNS="$TREE_IGNORE_PATTERNS|$base_pat"
fi
done
OUTPUT_FILE="${BASENAME}-dump.md"
{
echo "# PROJECT: $BASENAME"
echo "Generated on: $(date)"
echo -e "\n## PROJECT STRUCTURE"
echo '```text'
tree -n -I "$TREE_IGNORE_PATTERNS" "$TARGET_DIR"
echo '```'
echo -e "\n---\n"
echo "## SOURCE CODE CONTENTS"
while IFS= read -r -d '' file; do
# Пропускаем явно бинарные файлы по расширению, если нужно
# Но пока просто оформляем контент
ext="${file##*.}"
# Маппинг для расширений без которых ИИ грустит
case "$ext" in
h|hpp|c|cpp) lang="cpp" ;;
sh) lang="bash" ;;
py) lang="python" ;;
md) lang="markdown" ;;
*) lang="$ext" ;;
esac
# Если расширения нет
if [[ "$ext" == "$file" ]]; then lang="text"; fi
echo "### File: $file"
echo " \`\`\`$lang"
cat "$file"
echo -e "\n \`\`\`"
echo -e "\n---\n"
done < <("${FIND_CMD[@]}")
} > "$OUTPUT_FILE"
echo "Готово: $OUTPUT_FILE"