Use Markdown in output

This commit is contained in:
Кокос Артем Николаевич
2026-02-12 12:26:01 +07:00
parent 6ae9a00f3a
commit 7a51403a6a

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env bash
# projdump.sh - dump project structure and source code into a single text file
# projdump.sh - dump project structure and source code into a single Markdown file
set -euo pipefail
@@ -8,7 +8,7 @@ usage() {
Использование: $0 <директория>
Создаёт один файл:
<basename>-dump.txt — дерево проекта + содержимое исходных файлов
<basename>-dump.md — дерево проекта + содержимое файлов в Markdown
Игнорирует типичные артефакты сборки, кэши, IDE-файлы и зависимости.
@@ -29,109 +29,28 @@ if [[ ! -d "$TARGET_DIR" ]]; then
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
# Расширенный список игнорируемых паттернов
# Охватывает: Python, Node.js, Rust, Go, C/C++ (CMake, build dirs), Java, .NET, CI, OS, etc.
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"
"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-аргументов ===
@@ -149,10 +68,7 @@ FIND_CMD=(find "$TARGET_DIR" \( -false "${FIND_IGNORE_ARGS[@]}" \) -prune -o -ty
# === Подготовка шаблонов для tree ===
TREE_IGNORE_PATTERNS=""
for pat in "${IGNORE_LIST[@]}"; do
# tree работает только с именами, не путями → берём базовое имя
base_pat="${pat%%/*}"
# Убираем звёздочки? Нет — tree поддерживает glob, но * может мешать.
# Однако мы оставляем как есть, т.к. tree -I '*.pyc|node_modules' — нормально.
if [[ -z "$TREE_IGNORE_PATTERNS" ]]; then
TREE_IGNORE_PATTERNS="$base_pat"
else
@@ -160,24 +76,40 @@ for pat in "${IGNORE_LIST[@]}"; do
fi
done
OUTPUT_FILE="${BASENAME}-dump.txt"
OUTPUT_FILE="${BASENAME}-dump.md"
{
echo "========================================"
echo "PROJECT STRUCTURE (via tree)"
echo "========================================"
tree -I "$TREE_IGNORE_PATTERNS" "$TARGET_DIR"
echo -e "\n\n"
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 "========================================"
echo "SOURCE CODE CONTENTS"
echo "========================================"
echo "## SOURCE CODE CONTENTS"
while IFS= read -r -d '' file; do
echo "----------------------------------------"
echo "// FILE: $file"
echo "----------------------------------------"
# Пропускаем явно бинарные файлы по расширению, если нужно
# Но пока просто оформляем контент
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 \`\`\`"
echo -e "\n---\n"
done < <("${FIND_CMD[@]}")
} > "$OUTPUT_FILE"