tips.ps1
. $PSScriptRoot\Command.ps1 . $PSScriptRoot\Alias.ps1 function script:SeperateCommand() { param( [Parameter(Mandatory)][string]$Line ) if ($Line -match "(?<cmd>.*)(?<sep>;|(\|\|)|(&&))(?<rest>.*)") { if ($Debug) { Write-Host "Splliting line into $($matches['cmd']), $($matches['sep']), and $($matches['rest'])" } $LeftHalf = Find-Alias($matches['cmd']) $RightHalf = SeperateCommand $($matches['rest']) # If the left half isn't found restore the left half if (-not $LeftHalf) { $LeftHalf = $matches['cmd'] | Format-CleanCommand } # If the right half isn't found restore the right half if (-not $RightHalf) { $RightHalf = $matches['rest'] | Format-CleanCommand } $CompleteAlias = $($LeftHalf + "$(If ($matches['sep'] -eq ';') {''} else {' '})$($matches['sep']) " + $RightHalf) | Format-CleanCommand # only return the alias if it is different from the line if ($CompleteAlias -ne $($Line | Format-CleanCommand)) { return $CompleteAlias } } else { return Find-Alias($Line) } } function PSConsoleHostReadLine { ## Get the execution status of the last accepted user input. ## This needs to be done as the first thing because any script run will flush $?. $lastRunStatus = $? ($Line = [Microsoft.PowerShell.PSConsoleReadLine]::ReadLine($host.Runspace, $ExecutionContext, $lastRunStatus)) # split line into multiple commands if possible $alias = SeperateCommand $Line if ($alias -and -not $AliasTipsThreadJob -and $AliasHash.Length -gt 0) { # Only react to non-blank lines. $tip = "Alias tip: $alias" $host.UI.SupportsVirtualTerminal ? "`e[033m$tip`e[m" : $tip | Out-Host } } $script:AliasHash if ($Debug) { Write-Host $AliasHash } # Attempts to find an alias function Find-Alias() { param( [Parameter(Mandatory)][string]$Command ) # If we can find the alias quickly, do so $Alias = $AliasHash[$Command.Trim()] if ($Alias) { return $Alias } $Regex = Get-CommandMatcher $Command if ($Regex -eq "") { return "" } $Aliases = @("") if ($Debug) { Write-Host $Regex } $AliasHash.GetEnumerator() | ForEach-Object { if ($_.key -match $Regex) { $Aliases += $_.key } } if ($Debug) { Write-Host $Aliases } # Use the longest candiate $Alias = ($Aliases | Sort-Object -Descending -Property Length)[0] if ($Alias) { $Remaining = "$($Command)" $CleanAlias = "$($Alias)" | Format-CleanCommand $AttemptSplit = $CleanAlias -split " " $AttemptSplit | ForEach-Object { [Regex]$Pattern = [Regex]::Escape("$_") $Remaining = $Pattern.replace($Remaining, "", 1) } $Alias = ($AliasHash[$Alias] + $Remaining) | Format-CleanCommand if ($Remaining -and $AliasHash[$Alias + ' $args']) { $Alias = ($AliasHash[$Alias + ' $args'] + $Remaining) | Format-CleanCommand } if ($Alias -ne $Command) { return $Alias } } } function Find-AliasTips() { $CommandsPattern = Get-CommandsPattern # THANKS TO csc027 for the original code https://github.com/csc027 # Taken from: https://github.com/dahlbyk/posh-git/blob/ad8278e90ad8180c18e336676e490d921615e506/src/GitTabExpansion.ps1#L73-L87 # # The regular expression here is roughly follows this pattern: # # <begin anchor><whitespace>*<command>(<whitespace><parameter>)*<whitespace>+<$args><whitespace>*<end anchor> # # The delimiters inside the parameter list and between some of the elements are non-newline whitespace characters ([^\S\r\n]). # In those instances, newlines are only allowed if they preceded by a non-newline whitespace character. # # Begin anchor (^|[;`n]) # Whitespace (\s*) # Any Command (?<cmd>) # Parameters (?<params>(([^\S\r\n]|[^\S\r\n]``\r?\n)+\S+)*) # $args Anchor (([^\S\r\n]|[^\S\r\n]``\r?\n)+\`$args) # Whitespace (\s|``\r?\n)* # End Anchor ($|[|;`n]) $global:AliasTipsProxyFunctionRegex = $CommandsPattern | Get-ProxyFunctionRegex $global:AliasTipsProxyFunctionRegexNoArgs = $CommandsPattern | Get-ProxyFunctionRegexNoArgs $script:AliasHash = Get-AliasHash } function Start-FindAliasTips() { if (-not $script:AliasTipsThreadJob) { $script:AliasTipsThreadJob = Start-ThreadJob -Name 'Find-AliasTips' -StreamingHost $Host { return $(Get-CommandsPattern) } -ThrottleLimit 1 $JobResults = $AliasTipsThreadJob | Receive-Job $global:AliasTipsProxyFunctionRegex = $JobResults | Get-ProxyFunctionRegex $global:AliasTipsProxyFunctionRegexNoArgs = $JobResults | Get-ProxyFunctionRegexNoArgs $script:AliasHash = Get-AliasHash $script:AliasTipsThreadJob = $false } } if ($LoadAliasOnImport) { if ($SynchronousLoad) { Find-AliasTips } else { Start-FindAliasTips } } |