Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "PowerShell: Launch Current File",
"type": "PowerShell",
"request": "launch",
"script": "${file}",
"args": ["alias", "add", "source", "test"]
}
]
}
14 changes: 9 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,34 @@ qp or quickpath is a small cli project that I created in powershell and later al


# Installation
```powershell
```pwsh
Install-Module quickpath
```

# Usage
```powershell
```pwsh
qp [commands] [sub-commands]|[arguments]
```

## Aliases
An alias is added by passing it to the `alias add` command and passing a json object to it like:
```powershell
```pwsh
qp alias add '{"aliases": ["<myalias>"], "windowsPath": "the\\path\\to\\my\\alias" }'
```

```pwsh
qp alias add [alias] [path]
```

# Testing

For some of the logic I created unit tests. For powershell I use [Pester](https://pester.dev/docs/quick-start). Pester is installed using the following:
```powershell
```pwsh
Install-Module Pester -Force
```

And is the unit tests are run by using the following commands:
```powershell
```pwsh
Invoke-Pester
Invoke-Pester qp-path.Tests.ps1
Invoke-Pester -Output Detailed .\qp-path.Tests.ps1
Expand Down
5 changes: 3 additions & 2 deletions classes/Command.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,14 @@ class Command {
}

if ($this.FunctionPointer) {
& $this.FunctionPointer @($arguments)
& $this.FunctionPointer $arguments
}
else {
$subCommand = $this.SubCommands.Where({ $_.Name -eq $arguments[0] })

if ($subCommand) {
$subCommand.InvokeFunction($arguments[1..($arguments.length - 1)])
$remainingArguments = $arguments[1..($arguments.length - 1)]
$subCommand.InvokeFunction($remainingArguments)
}
else {
Write-Host "No function assigned for command: $($this.Name) $($arguments[0])"
Expand Down
99 changes: 89 additions & 10 deletions private/Alias-Helper.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,30 @@ function Get-Script-Path {
$file = Join-Path $appData 'aliases.json'

if (-not (Test-Path $file)) {
'[]' | New-Item -Path $file -ItemType File -Force | Out-Null
'[]' | Out-File -Path $file
}

return $file
return $file
}


function Import-Aliases {
if (!(Test-Path $script:JSON_FILE_PATH)) {
New-Item -Path $script:JSON_FILE_PATH -ItemType File
'[]' | Out-File -Path $script:JSON_FILE_PATH
}

$json = Get-Content -Raw -Path $script:JSON_FILE_PATH
return [AliasPathMapping[]][AliasPathMapping]::FromJsonArray($json)
if ([string]::IsNullOrEmpty($json)) {
$json = '[]'
}

try {
return [AliasPathMapping[]][AliasPathMapping]::FromJsonArray($json)
}
catch {
Write-Warning "Failed to parse aliases JSON; returning empty list. $_"
return @()
}
}

function Get-Alias([string[]]$aliases) {
Expand All @@ -36,17 +46,77 @@ function Get-Alias([string[]]$aliases) {
return $null
}

function Add-Alias([string]$jsonString) {
function Resolve-FullPath([string]$path) {
if ([string]::IsNullOrEmpty($path)) { return $path }

# expand ~ to user home
if ($path -like '~*') {
$path = $path -replace '^(~)', $HOME
}

# If already rooted (C:\, \\server\share, / on Linux) get full path
if ([System.IO.Path]::IsPathRooted($path)) {
return [System.IO.Path]::GetFullPath($path)
}

# otherwise combine with current location and get full path
$base = (Get-Location).ProviderPath
return [System.IO.Path]::GetFullPath((Join-Path $base $path))
}

function Add-Alias([string]$argument1, [string]$argument2) {
if (-not [string]::IsNullOrEmpty($argument2) ) {
Add-AliasFromPath -alias $argument1 -path $argument2
}
else {
Add-AliasFromJson($argument1)
}

$json = [AliasPathMapping]::ToJson($script:ALIASES)
$json | Out-File $script:JSON_FILE_PATH
}

function Add-AliasFromPath([string]$alias, [string]$path) {
$resolvedPath = Resolve-FullPath $path

if (-not (Test-Path $resolvedPath)) {
Write-Error "Path does not exist: $resolvedPath"
return $script:ALIASES
}

$script:ALIASES = @($script:ALIASES)

$newAliasPath = [AliasPathMapping]::new()
$newAliasPath.Aliases = @($alias)
$newAliasPath.WindowsPath = $resolvedPath

$aliases = $newAliasPath.Aliases
$aliasPath = (Get-Alias $aliases)

if ($aliasPath) {
$aliasPath.Aliases = ($newAliasPath.Aliases + $aliasPath.Aliases) | Select-Object -Unique
$aliasPath.WindowsPath = [String]::IsNullOrEmpty($newAliasPath.WindowsPath) ? $aliasPath.WindowsPath : $newAliasPath.WindowsPath
$aliasPath.LinuxPath = [String]::IsNullOrEmpty($newAliasPath.LinuxPath) ? $aliasPath.LinuxPath : $newAliasPath.LinuxPath
$aliasPath.Solution = [String]::IsNullOrEmpty($newAliasPath.Solution) ? $aliasPath.Solution : $newAliasPath.Solution
}
else {
$script:ALIASES += $newAliasPath
}

return $script:ALIASES
}

function Add-AliasFromJson([string]$jsonString) {
$script:ALIASES = @($script:ALIASES)
$newAliasPath = [AliasPathMapping]::FromJson($jsonString)

if (!($newAliasPath)) {
Write-Output "Could not add alias"
Write-Error "Could not add alias"
return $script:ALIASES
}

if ($newAliasPath.Aliases.Count -eq 0) {
Write-Output "No Aliases defined"
Write-Error "No Aliases defined"
return $script:ALIASES
}

Expand All @@ -63,12 +133,21 @@ function Add-Alias([string]$jsonString) {
$script:ALIASES += $newAliasPath
}

$json = [AliasPathMapping]::ToJson($script:ALIASES)
$json | Out-File $script:JSON_FILE_PATH
return $script:ALIASES
}

function Remove-Alias([string] $alias) {
$script:ALIASES = $script:ALIASES | Where-Object { $_.aliases -notcontains $alias }
$script:ALIASES = @($script:ALIASES)

# If alias isn't present anywhere, do nothing
if (-not ($script:ALIASES | Where-Object { $_.Aliases -contains $alias })) {
return $script:ALIASES
}

# Remove mappings that contain the alias and persist only if changed
$script:ALIASES = $script:ALIASES | Where-Object { $_.Aliases -notcontains $alias }
$json = [AliasPathMapping]::ToJson($script:ALIASES)
$json | Out-File $script:JSON_FILE_PATH

return $script:ALIASES
}
8 changes: 2 additions & 6 deletions quickpath.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,7 @@
RootModule = 'quickpath.psm1'

# Version number of this module.
ModuleVersion = '0.0.3'

# Supported PSEditions
# CompatiblePSEditions = @()

ModuleVersion = '0.14.3'
# ID used to uniquely identify this module
GUID = '376719b2-2cdd-47e8-b82b-b01870c08ac8'

Expand Down Expand Up @@ -131,4 +127,4 @@
# DefaultCommandPrefix = ''

}

4 changes: 3 additions & 1 deletion quickpath.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -121,4 +121,6 @@ Register-ArgumentCompleter -CommandName qp -ScriptBlock {
return "$matched"
}
}
}
}

Export-ModuleMember -Function qp
Loading