Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1.1.0 #26

Merged
merged 15 commits into from
May 6, 2024
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2023 Cody Duong, and contributers
Copyright (c) 2023-2024 Cody Duong, and contributers

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
4 changes: 4 additions & 0 deletions alias-tips/Private/Find-AliasCommand.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ function Find-AliasCommand {
# TODO check if it is an alias, expand it back out to check if there is a better alias

# We failed to find the alias in the hash, instead get the executed command, and attempt to generate a regex for it.

# First we need to ensure we have generated required regexes
Find-RegexThreadJob
# Generate a regex that searches through our alias hash, and checks if it matches as an alias for our command
$Regex = Get-CommandRegex $Command
if ([string]::IsNullOrEmpty($Regex)) {
return ""
Expand Down
18 changes: 18 additions & 0 deletions alias-tips/Private/Find-RegexThreadJob.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
function Find-RegexThreadJob {
if ($null -ne $global:AliasTipsProxyFunctionRegex -and $null -ne $global:AliasTipsProxyFunctionRegexNoArgs) {
Fixed Show fixed Hide fixed
Fixed Show fixed Hide fixed
return
}

$existingJob = Get-Job -Name "FindAliasTipsJob"
if ($null -ne $existingJob) {
$existingJob = Wait-Job -Job $existingJob
}
else {
$job = Start-RegexThreadJob

$existingJob = Wait-Job -Job $job
}
$result = Receive-Job -Job $existingJob -Wait -AutoRemoveJob

$global:AliasTipsProxyFunctionRegex, $global:AliasTipsProxyFunctionRegexNoArgs = $result
Fixed Show fixed Hide fixed
Fixed Show fixed Hide fixed
}
1 change: 1 addition & 0 deletions alias-tips/Private/Get-Aliases.ps1
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Return a hashtable of possible aliases
function Get-Aliases {
$Hash = @{}
Find-RegexThreadJob

# generate aliases for commands aliases created via native PowerShell functions
$proxyAliases = Get-Item -Path Function:\
Expand Down
12 changes: 2 additions & 10 deletions alias-tips/Private/Get-CommandRegex.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,12 @@ function Get-CommandRegex {
[OutputType([System.String])]
param (
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[string]${Command},

[Parameter()]
[switch]${Simple}
[string]${Command}
)

process {
if ($Simple) {
$CleanCommand = $Command | Format-Command
return "(" + ([Regex]::Escape($CleanCommand) -split " " -join "|") + ")"
}

# The parse is a bit naive...
if ($Command -match $AliasTipsProxyFunctionRegexNoArgs) {
if ($Command -match $global:AliasTipsProxyFunctionRegexNoArgs) {
Fixed Show fixed Hide fixed
# Clean up the command by removing extra delimiting whitespace and backtick preceding newlines
$CommandString = ("$($matches['cmd'].TrimStart())") | Format-Command

Expand Down
14 changes: 0 additions & 14 deletions alias-tips/Private/Get-CommandsRegex.ps1

This file was deleted.

24 changes: 0 additions & 24 deletions alias-tips/Private/Get-ProxyFunctionRegex.ps1

This file was deleted.

53 changes: 53 additions & 0 deletions alias-tips/Private/Start-RegexThreadJob.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
function Start-RegexThreadJob {
Fixed Show fixed Hide fixed
Fixed Show fixed Hide fixed
$existingJob = Get-Job -Name "FindAliasTipsJob" -ErrorAction SilentlyContinue | Select-Object -Last 1
if ($null -ne $existingJob) {
$existingJob = Wait-Job -Job $existingJob
}

return Start-ThreadJob -Name "FindAliasTipsJob" -ScriptBlock {
function Get-CommandsRegex {
(Get-Command * | ForEach-Object {
$CommandUnsafe = $_ | Select-Object -ExpandProperty 'Name'
$Command = [Regex]::Escape($CommandUnsafe)
# check if it has a file extensions
if ($CommandUnsafe -match "(?<cmd>[^.\s]+)\.(?<ext>[^.\s]+)$") {
$CommandWithoutExtension = [Regex]::Escape($matches['cmd'])
return $Command, $CommandWithoutExtension
}
else {
return $Command
}
}) -Join '|'
}

# The regular expression here 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])
function Get-ProxyFunctionRegexes {
Fixed Show fixed Hide fixed
param (
[Parameter(Mandatory, Position = 0, ValueFromPipeline = $true)][regex]${CommandPattern}
)

process {
[regex]"(^|[;`n])(\s*)(?<cmd>($CommandPattern))(?<params>(([^\S\r\n]|[^\S\r\n]``\r?\n)+\S+)*)(([^\S\r\n]|[^\S\r\n]``\r?\n)+\`$args)(\s|``\r?\n)*($|[|;`n])",
[regex]"(^|[;`n])(\s*)(?<cmd>($CommandPattern))(?<params>(([^\S\r\n]|[^\S\r\n]``\r?\n)+\S+)*)(\s|``\r?\n)*($|[|;`n])"
}
}


Get-CommandsRegex | Get-ProxyFunctionRegexes
}
}

Start-RegexThreadJob | Out-Null
181 changes: 108 additions & 73 deletions alias-tips/Public/Find-Alias.ps1
Original file line number Diff line number Diff line change
@@ -1,95 +1,130 @@
# Attempts to find an alias for a command string (ie. can consist of chained or nested aliases)
function Find-Alias {
<#
.SYNOPSIS

Finds an alias for a command string.

.DESCRIPTION

Finds an alias for a command string. Returns the original line if no aliases are found.

.PARAMETER Line

Specifies the line to find an alias for.

.OUTPUTS

System.String. Find-Alias will return an alias or the original line if none are found.

.EXAMPLE

PS> Find-Alias "git checkout master"
gcm

.EXAMPLE

PS> Find-Alias -Line "git status"
gst

#>
param(
[Parameter(Mandatory)][string]$Line
[Parameter(Mandatory, ValueFromPipeline = $true)]
[string]$Line
)

$tokens = @()
$ast = [System.Management.Automation.Language.Parser]::ParseInput($Line, [ref]$tokens, [ref]$null)
process {
if ($AliasTipsHash -and $AliasTipsHash.Count -eq 0) {
$AliasTipsHash = ConvertFrom-StringData -StringData $([System.IO.File]::ReadAllText($AliasTipsHashFile)) -Delimiter "|"
}

$fastAlias = Find-AliasCommand ($tokens.Text -join " ")
$tokens = @()
$ast = [System.Management.Automation.Language.Parser]::ParseInput($Line, [ref]$tokens, [ref]$null)

if (-not [string]::IsNullOrEmpty($fastAlias)) {
Write-Verbose "Found alias without resorting to parsing"
return $fastAlias
}
$fastAlias = Find-AliasCommand ($tokens.Text -join " ")

$queue = [System.Collections.ArrayList]::new()
$extents = @(0, 0)
$offset = 0
$aliased = $ast.ToString()

foreach ($token in $tokens) {
$kind = $token.Kind
# Write-Host ($kind, "'$($token.Text)'" , $token.Extent.StartOffset, $token.Extent.EndOffset)
if ('Generic', 'Identifier', 'HereStringLiteral', 'Parameter', 'StringLiteral' -contains $kind) {
if ($queue.Count -eq 0) {
$queue += $token.Text
$extents = @($token.Extent.StartOffset, $token.Extent.EndOffset)
}
else {
$queue[-1] = "$($queue[-1]) $($token.Text)"
$extents = @($extents[0], $token.Extent.EndOffset)
}
if (-not [string]::IsNullOrEmpty($fastAlias)) {
Write-Verbose "Found alias without resorting to parsing"
return $fastAlias
}
else {
# When we finish the current token back-alias it
if ($queue.Count -gt 0) {
$alias = Find-AliasCommand $queue[-1]
if (-not [string]::IsNullOrEmpty($alias)) {
$saved = $queue[-1].Length - $alias.Length
$newleft = $extents[0] + $offset
$newright = $extents[1] + $offset
$aliased = "$(if ($newLeft -le 0) {''} else {$aliased.Substring(0, $newLeft)})$alias$(if ($newright -ge $aliased.Length) {''} else {$aliased.Substring($newright)})"
$offset -= $saved

$queue = [System.Collections.ArrayList]::new()
$extents = @(0, 0)
$offset = 0
$aliased = $ast.ToString()

foreach ($token in $tokens) {
$kind = $token.Kind
Write-Verbose "$(($kind, "'$($token.Text)'" , $token.Extent.StartOffset, $token.Extent.EndOffset))"
if ('Generic', 'Identifier', 'HereStringLiteral', 'Parameter', 'StringLiteral' -contains $kind) {
if ($queue.Count -eq 0) {
$queue += $token.Text
$extents = @($token.Extent.StartOffset, $token.Extent.EndOffset)
}
else {
$queue[-1] = "$($queue[-1]) $($token.Text)"
$extents = @($extents[0], $token.Extent.EndOffset)
}
}
else {
# When we finish the current token back-alias it
if ($queue.Count -gt 0) {
Write-Verbose "fuck $($queue[-1])"
$alias = Find-AliasCommand $queue[-1]
if (-not [string]::IsNullOrEmpty($alias)) {
$saved = $queue[-1].Length - $alias.Length
$newleft = $extents[0] + $offset
$newright = $extents[1] + $offset
$aliased = "$(if ($newLeft -le 0) {''} else {$aliased.Substring(0, $newLeft)})$alias$(if ($newright -ge $aliased.Length) {''} else {$aliased.Substring($newright)})"
$offset -= $saved
}
}

# Reset the queue
$queue = [System.Collections.ArrayList]::new()
$extents = @(0, 0)
# Reset the queue
$queue = [System.Collections.ArrayList]::new()
$extents = @(0, 0)

if ('HereStringExpandable', 'StringExpandable' -contains $kind) {
$ntokens = $token.NestedTokens
if ($ntokens.Length -eq 0) {
continue
}
$nqueue = [System.Collections.ArrayList]::new()
$nextents = @(0, 0)
foreach ($ntoken in $ntokens) {
$nkind = $ntoken.Kind
# Write-Host ("`t", $nkind, "'$($ntoken.Text)'" , $ntoken.Extent.StartOffset, $ntoken.Extent.Endoffset)
if ('Generic', 'Identifier', 'HereStringLiteral', 'Parameter', 'StringLiteral' -contains $nkind) {
if ($nqueue.Count -eq 0) {
$nqueue += $ntoken.Text
$nextents = @($ntoken.Extent.StartOffset, $ntoken.Extent.EndOffset)
}
else {
$nqueue[-1] = "$($nqueue[-1]) $($ntoken.Text)"
$nextents = @($nextents[0], $ntoken.Extent.EndOffset)
}
if ('HereStringExpandable', 'StringExpandable' -contains $kind) {
$ntokens = $token.NestedTokens
if ($ntokens.Length -eq 0) {
continue
}
else {
# When we finish the current token back-alias it
if ($nqueue.Count -gt 0) {
$alias = Find-AliasCommand $nqueue[-1]
if (-not [string]::IsNullOrEmpty($alias)) {
$saved = $nqueue[-1].Length - $alias.Length
$newleft = $nextents[0] + $offset
$newright = $nextents[1] + $offset
$aliased = "$(if ($newLeft -le 0) {''} else {$aliased.Substring(0, $newLeft)})$alias$(if ($newright -ge $aliased.Length) {''} else {$aliased.Substring($newright)})"
$offset -= $saved
$nqueue = [System.Collections.ArrayList]::new()
$nextents = @(0, 0)
foreach ($ntoken in $ntokens) {
$nkind = $ntoken.Kind
# Write-Host ("`t", $nkind, "'$($ntoken.Text)'" , $ntoken.Extent.StartOffset, $ntoken.Extent.Endoffset)
if ('Generic', 'Identifier', 'HereStringLiteral', 'Parameter', 'StringLiteral' -contains $nkind) {
if ($nqueue.Count -eq 0) {
$nqueue += $ntoken.Text
$nextents = @($ntoken.Extent.StartOffset, $ntoken.Extent.EndOffset)
}
else {
$nqueue[-1] = "$($nqueue[-1]) $($ntoken.Text)"
$nextents = @($nextents[0], $ntoken.Extent.EndOffset)
}
}
else {
# When we finish the current token back-alias it
if ($nqueue.Count -gt 0) {
$alias = Find-AliasCommand $nqueue[-1]
if (-not [string]::IsNullOrEmpty($alias)) {
$saved = $nqueue[-1].Length - $alias.Length
$newleft = $nextents[0] + $offset
$newright = $nextents[1] + $offset
$aliased = "$(if ($newLeft -le 0) {''} else {$aliased.Substring(0, $newLeft)})$alias$(if ($newright -ge $aliased.Length) {''} else {$aliased.Substring($newright)})"
$offset -= $saved
}
}

# Reset the queue
$nqueue = [System.Collections.ArrayList]::new()
$nextents = @(0, 0)
# Reset the queue
$nqueue = [System.Collections.ArrayList]::new()
$nextents = @(0, 0)
}
}
}
}
}
}

$aliased.Trim()
$aliased.Trim()
}
}
2 changes: 0 additions & 2 deletions alias-tips/Public/Find-AliasTips.ps1
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
function Find-AliasTips {
$global:AliasTipsProxyFunctionRegex, $global:AliasTipsProxyFunctionRegexNoArgs = Get-CommandsRegex | Get-ProxyFunctionRegexes

$AliasTipsHash = Get-Aliases
$Value = $($AliasTipsHash.GetEnumerator() | ForEach-Object {
if ($_.Key.Length -ne 0) {
Expand Down
Loading