0.1.0/Public/Find-Item.ps1

function Find-Item {
    <#
    .SYNOPSIS
        Developer-first search tool for files and content.
    .DESCRIPTION
        Searches for files by name or content, skipping common build/dependency directories (node_modules, .git, etc.) for performance.
    .EXAMPLE
        search "LoginController"
        Finds files with "LoginController" in the name.
    .EXAMPLE
        search "TODO" -Content
        Finds "TODO" inside files.
    .EXAMPLE
        search "error" -Content -Context 2
        Finds "error" inside files and shows 2 lines of context.
    #>

    [CmdletBinding()]
    [Alias('search')]
    param(
        [Parameter(Mandatory = $true, Position = 0)]
        [string]$Pattern,

        [switch]$Content,

        [int]$Context = 0,

        [switch]$Regex,

        [switch]$CaseSensitive,

        [switch]$Raw
    )

    begin {
        $Blocklist = @(
            '.git', '.svn', '.hg', '.vscode', '.idea',
            'node_modules', 'bower_components', 'packages',
            'bin', 'obj', 'dist', 'build', 'out', 'target',
            '__pycache__', 'vendor', 'terraform.tfstate.d'
        )

        $BinaryExtensions = @(
            '.exe', '.dll', '.iso', '.png', '.zip', '.jpg', '.jpeg', '.gif', '.bmp', '.ico',
            '.pdf', '.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx', '.7z', '.tar', '.gz', '.rar',
            '.pdb', '.suo', '.cache', '.class', '.jar', '.war', '.ear', '.mp3', '.mp4', '.mov'
        )

        $MaxFileSize = 50MB
        $StartPath = (Get-Location).ProviderPath
        $Queue = [System.Collections.Generic.Queue[string]]::new()
        $Queue.Enqueue($StartPath)

        # Compile Regex for highlighting/matching
        $RegexOptions = [System.Text.RegularExpressions.RegexOptions]::None
        if (-not $CaseSensitive) {
            $RegexOptions = $RegexOptions -bor [System.Text.RegularExpressions.RegexOptions]::IgnoreCase
        }

        if (-not $Regex) {
            $MatchPattern = [System.Text.RegularExpressions.Regex]::Escape($Pattern)
        } else {
            $MatchPattern = $Pattern
        }
        
        $SearchPatternObj = try {
            [System.Text.RegularExpressions.Regex]::new($MatchPattern, $RegexOptions)
        } catch {
            Write-Error "Invalid Regex Pattern: $_"
            return
        }
    }

    process {
        while ($Queue.Count -gt 0) {
            $currentPath = $Queue.Dequeue()
            
            try {
                $dirInfo = [System.IO.DirectoryInfo]::new($currentPath)
                $entries = $dirInfo.GetFileSystemInfos()
            } catch {
                Write-Verbose "Access denied or error reading: $currentPath"
                continue
            }

            foreach ($entry in $entries) {
                if ($entry.Attributes.HasFlag([System.IO.FileAttributes]::Directory)) {
                    if ($Blocklist -notcontains $entry.Name) {
                        $Queue.Enqueue($entry.FullName)
                    }
                } else {
                    # It's a file
                    if ($Content) {
                        # Content Search Mode
                        if ($BinaryExtensions -contains $entry.Extension) { continue }
                        if ($entry.Length -gt $MaxFileSize) { continue }

                        $slsParams = @{
                            Path = $entry.FullName
                            Pattern = $MatchPattern
                            CaseSensitive = $CaseSensitive
                            Context = $Context
                            AllMatches = $false
                        }
                        
                        $matches = Select-String @slsParams
                        
                        if ($matches) {
                            if ($Raw) {
                                $matches | Write-Output
                            } else {
                                Format-ContentMatch -Matches $matches -PatternObj $SearchPatternObj -File $entry.FullName
                            }
                        }

                    } else {
                        # Name Search Mode
                        if ($SearchPatternObj.IsMatch($entry.Name)) {
                            if ($Raw) {
                                Write-Output $entry
                            } else {
                                Format-NameMatch -FileInfo $entry -Root $StartPath
                            }
                        }
                    }
                }
            }
        }
    }
}