Skip to content

Instantly share code, notes, and snippets.

@JustSuperHuman
Created October 27, 2024 04:43
Show Gist options
  • Save JustSuperHuman/cc4fcd46a8fed38280090d77b5412663 to your computer and use it in GitHub Desktop.
Save JustSuperHuman/cc4fcd46a8fed38280090d77b5412663 to your computer and use it in GitHub Desktop.
# Directory Tree Generator
param(
[Parameter(Mandatory=$false)]
[string]$RootPath = (Get-Location),
[Parameter(Mandatory=$false)]
[string]$OutputFile = "api-tree.list"
)
# Default ignore patterns
$defaultIgnorePatterns = @(
# Build output directories
'bin/**',
'**/bin/**',
'obj/**',
'**/obj/**',
'dist/**',
'build/**',
# Migration files
'**/Migrations/**',
'*.Migration.*',
'**/Migration*/**',
# Debug and temporary files
'**/Debug/**',
'**/Release/**',
'*.pdb',
'*.dll',
'*.exe',
'*.cache',
'*.json',
'**/refint/**',
'**/ref/**',
'**/staticwebassets/**',
'*.editorconfig',
'*.BuildWithSkipAnalyzers',
'*.FileListAbsolute.txt',
'*.AssemblyInfo.cs',
'*.GeneratedMSBuildEditorConfig.*',
'*.GlobalUsings.g.cs',
'*.sourcelink.json',
'*.Up2Date',
# VS and IDE files
'.vs/**',
'.vscode/**',
'.idea/**',
# Package directories
'packages/**',
'node_modules/**',
# Environment and config files
'.env*',
'**/appsettings*.json',
'**/launchSettings.json',
# Project specific
'**/justgains*',
'.*//**',
# Other common ignore patterns
'*.log',
'*.pyc',
'__pycache__/**',
'target/**'
)
function Add-GitignorePatterns {
param(
[string]$GitignorePath,
[array]$IgnorePatterns
)
if (Test-Path $GitignorePath) {
$gitignoreContent = Get-Content $GitignorePath
foreach ($line in $gitignoreContent) {
if (![string]::IsNullOrWhiteSpace($line) -and !$line.StartsWith('#')) {
$IgnorePatterns += $line.Trim()
}
}
}
return $IgnorePatterns
}
function Test-ShouldIgnore {
param(
[string]$Path,
[array]$IgnorePatterns,
[string]$RootPath
)
# Convert to forward slashes for consistency and trim root path
$relativePath = $Path.Replace($RootPath, '').Replace('\', '/').TrimStart('/')
foreach ($pattern in $IgnorePatterns) {
$pattern = $pattern.Replace('\', '/').TrimStart('/')
# Handle directory patterns with **
if ($pattern.Contains('**')) {
$regex = '^' + [regex]::Escape($pattern).Replace('\*\*', '.*').Replace('\*', '[^/]*') + '$'
if ($relativePath -match $regex) {
return $true
}
}
# Handle exact directory matches
elseif ($pattern.EndsWith('/')) {
if ($relativePath.StartsWith($pattern.TrimEnd('/'))) {
return $true
}
}
# Handle wildcard patterns
elseif ($pattern.Contains('*')) {
$regex = '^' + [regex]::Escape($pattern).Replace('\*', '[^/]*') + '$'
if ($relativePath -match $regex) {
return $true
}
}
# Handle exact matches
elseif ($relativePath -eq $pattern) {
return $true
}
}
return $false
}
function Get-DirectoryTree {
param(
[string]$Path,
[array]$IgnorePatterns,
[string]$RootPath,
[string]$Prefix = "",
[bool]$IsLast = $true
)
$basename = Split-Path $Path -Leaf
$newPrefix = $Prefix + $(if ($IsLast) { " " } else { "│ " })
$result = $Prefix + $(if ($IsLast) { "└── " } else { "├── " }) + $basename + "`n"
try {
$items = Get-ChildItem -Path $Path | Where-Object {
!(Test-ShouldIgnore -Path $_.FullName -IgnorePatterns $IgnorePatterns -RootPath $RootPath)
}
$itemCount = $items.Count
$currentItem = 0
foreach ($item in $items) {
$currentItem++
$isLastItem = $currentItem -eq $itemCount
if ($item.PSIsContainer) {
$result += Get-DirectoryTree -Path $item.FullName -IgnorePatterns $IgnorePatterns -RootPath $RootPath -Prefix $newPrefix -IsLast $isLastItem
}
else {
$result += $newPrefix + $(if ($isLastItem) { "└── " } else { "├── " }) + $item.Name + "`n"
}
}
}
catch {
Write-Error "Error reading directory $Path : $_"
}
return $result
}
# Main execution
try {
$ignorePatterns = $defaultIgnorePatterns
$gitignorePath = Join-Path $RootPath ".gitignore"
$ignorePatterns = Add-GitignorePatterns -GitignorePath $gitignorePath -IgnorePatterns $ignorePatterns
$tree = Get-DirectoryTree -Path $RootPath -IgnorePatterns $ignorePatterns -RootPath $RootPath
$tree | Out-File -FilePath $OutputFile -Encoding utf8
Write-Host "Tree structure has been written to $OutputFile"
}
catch {
Write-Error "An error occurred: $_"
exit 1
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment