diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fb412a6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +profile.d/env.ps1 diff --git a/Edit-MyProfiles.ps1 b/Edit-MyProfiles.ps1 new file mode 100644 index 0000000..4bfa455 --- /dev/null +++ b/Edit-MyProfiles.ps1 @@ -0,0 +1,6 @@ +[CmdletBinding(SupportsShouldProcess)]param( + [switch]$sudo, + [switch]$Force +) + +Edit-TextFile -sudo:$sudo $( Get-Profiles | Where-Object { $_.Exists -or $Force } | Select-Object -ExpandProperty Path ) diff --git a/Edit-MyScript.ps1 b/Edit-MyScript.ps1 new file mode 100644 index 0000000..3e631ec --- /dev/null +++ b/Edit-MyScript.ps1 @@ -0,0 +1,47 @@ +[CmdletBinding(SupportsShouldProcess)]param( + [ArgumentCompleter({ param ( + $commandName, + $parameterName, + $wordToComplete, + $commandAst, + $fakeBoundParameters + ) + [FunctionName]::_GetValidValues($wordToComplete,$true) + })] + [string[]]$ImportFunction, + [switch]$ForceImport, + [Parameter(Position = 0, ValueFromRemainingArguments = $true)] + [ArgumentCompleter({ param ( + $commandName, + $parameterName, + $wordToComplete, + $commandAst, + $fakeBoundParameters + ) + [MyScript]::_GetValidValues($wordToComplete,$false) + })] + [string[]]$ScriptName +) + +$local:ScriptPaths = @() +foreach( $local:p in $ImportFunction ) { + $local:f = Get-Command $p -Type Function + if( $f ) { + $local:sp = Join-Path $MyPSScriptRoot "$p`.ps1" + if( $ForceImport -or -not (Test-Path $sp) ) { + Export-FunctionSource $p -NoHeader > $sp + } elseif ( -not $ForceImport ) { + throw "$p already exists in Script, to import the function again, use the -Force" + } + $ScriptPaths += $sp + } +} +foreach( $local:p in $ScriptName ) { + $local:sp = Join-Path $MyPSScriptRoot "$p`.ps1" + $ScriptPaths += $sp +} + +Edit-TextFile $ScriptPaths + +Get-Command Reload-MyScripts -ErrorAction SilentlyContinue | + ForEach-Object { . $_.Definition } diff --git a/Edit-TextFile.ps1 b/Edit-TextFile.ps1 new file mode 100644 index 0000000..54660a5 --- /dev/null +++ b/Edit-TextFile.ps1 @@ -0,0 +1,25 @@ +[CmdletBinding(SupportsShouldProcess)]param( + [switch]$sudo, + [Parameter(Position = 0, ValueFromRemainingArguments = $true)] + [string[]]$Path +) + +$local:editor = '/bin/nvim' +if( (Test-Path env:EDITOR) -and (Test-Path $env:EDITOR) ) { + $editor = $env:EDITOR; +} + +if( $editor -match 'vim?$' ) { + $editor += ' -p' +} + +if( $sudo ) { + $editor = "sudo $editor" +} + +$local:arguments = $Path -join "' '" +if( $Path ) { $arguments = "'$arguments'" } + +if( $PSCmdlet.ShouldProcess( "Edit ($editor): $arguments" ) ) { + Invoke-Expression "$editor $arguments" +} diff --git a/Export-FunctionSource.ps1 b/Export-FunctionSource.ps1 new file mode 100644 index 0000000..29cb4c4 --- /dev/null +++ b/Export-FunctionSource.ps1 @@ -0,0 +1,16 @@ +param( + [switch]$NoHeader, + [Parameter(Position = 0, ValueFromRemainingArguments = $true)] + #[ValidateSet([Functions])] + [string[]]$FunctionName + +) + +$local:src = "" +foreach( $local:func in $FunctionName ) { + if( -not $NoHeader ) { $src += "`nfunction $func {" } + $src += "`n $((Get-Command -Type Function $func).Definition)" + if( -not $NoHeader ) { $src += "`n}" } + $src += "`n" +} +return $src.Trim() diff --git a/Get-MyAliases.ps1 b/Get-MyAliases.ps1 index a836f38..ddcbcef 100644 --- a/Get-MyAliases.ps1 +++ b/Get-MyAliases.ps1 @@ -9,17 +9,18 @@ do { try { $local:newAliases += Get-Alias -Scope $_scope | Where-Object { - ($_.Definition -match "^$MyPSScrtipRoot") -or ($_.Description -match '#MyAlias') + ($_.Definition -match "^$MyPSScriptRoot") -or ($_.Description -match '#MyAlias') } if( $newAliases ) { $allAliases += $newAliases $MyAliasScope = $_scope; Write-Verbose "`$MyAliasScope is now set to $MyAliasScope" } - $_scope += 1 } catch { - $done = $_.Exception.Message -match 'The scope .* exceeds' + Write-Verbose "catch: $($_.Exception.Message)" + $_done = $_.Exception.Message -match 'The scope .* exceeds' } -} until ( $done ) + $_scope += 1 +} until ( $_done ) $allAliases diff --git a/Get-MyScript.ps1 b/Get-MyScript.ps1 new file mode 100644 index 0000000..f438b76 --- /dev/null +++ b/Get-MyScript.ps1 @@ -0,0 +1,8 @@ +[CmdletBinding()]param( + [string]$Filter, + [switch]$NamesOnly +) +$local:rVal = [MyScript]::_GetValidValues($Filter,$true) +if( $NamesOnly ) { return $rVal } +return $rVal | ForEach-Object { Join-Path $MyPSScriptRoot "$_`.ps1" } + diff --git a/Get-PossibleArguments.ps1 b/Get-PossibleArguments.ps1 new file mode 100644 index 0000000..0a1ade0 --- /dev/null +++ b/Get-PossibleArguments.ps1 @@ -0,0 +1,13 @@ +[CmdletBinding()]param( + [string]$WordToComplete, + [string[]]$FullValueSet, + [switch]$Strict +) + $local:possibleValues = $fullValueSet + if( $wordToComplete ) { + $possibleValues = $possibleValues | Where-Object { $_ -match $wordToComplete } + if( -not $strict -and ($wordToComplete -notin $possibleValues) ) { + $possibleValues = $( $wordToComplete; $possibleValues ) + } + } +return $possibleValues diff --git a/Get-Profiles.ps1 b/Get-Profiles.ps1 new file mode 100644 index 0000000..0cd1acb --- /dev/null +++ b/Get-Profiles.ps1 @@ -0,0 +1,13 @@ +[CmdletBinding()]param( + [switch]$AsDictionary +) + +filter ConvertTo-Hash { param([string]$Property="Name") begin { $hash = @{} } process{ $hash[$_."$Property"] = $_ } end {return $hash} } + +$local:rVal = $PROFILE | fl * -Force | Out-String -Stream | Where-Object { $_ -match '( : /)|(:\\)' } | + Select-Object @{ + N="Profile";E={($_ -split ": ")[0].Trim()} + },@{N="Path";E={($_ -split ": ")[-1].Trim()} +} | Select-Object *,@{N="Exists";E={Test-Path $_.Path}} +if( $AsDictionary ) { return $rVal | ConvertTo-Hash -Property "Profile" } +return $rVal diff --git a/Get-ScopeDepth.ps1 b/Get-ScopeDepth.ps1 new file mode 100644 index 0000000..6a9d3c7 --- /dev/null +++ b/Get-ScopeDepth.ps1 @@ -0,0 +1,2 @@ +$local:_scope = 0; +while ($true) { try { Get-Variable -Scope $_scope | Out-Null; $_scope += 1 } catch { return ($_scope - 1) } } diff --git a/README.md b/README.md index 516bdda..a6b3396 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ The scripts all [assume](https://blog.lksz.me/functions-or-scripts/#myprofilecod The code establishes the following variables: * `$PathEnvDelimiter` - Linux/Unix it's `:`, while in Windows it's `;` * `$MyPSModulePath` - Location to place personal Modules -* `$MyPSScrtipRoot` - Location of personal Scripts. +* `$MyPSScriptRoot` - Location of personal Scripts. The code also makes sure `$MyPSScriptRoot` is in the `$env:PATH` environment vairable, and finally it calls [`Reload-MyAliases`](https://blog.lksz.me/a-case-of-sensitivity/#myaliases) if it exists. @@ -34,13 +34,13 @@ if( -not $MyPSModulePath ) { } $local:p = Split-PathEnv $env:PATH -$global:MyPSScrtipRoot = Join-Path (Split-Path -Parent $MyPSModulePath) Scripts -if( -not (Test-Path $MyPSScrtipRoot) ) { - New-Item -ItemType Directory -Path $MyPSScrtipRoot -Force | Out-Null +$global:MyPSScriptRoot = Join-Path (Split-Path -Parent $MyPSModulePath) Scripts +if( -not (Test-Path $MyPSScriptRoot) ) { + New-Item -ItemType Directory -Path $MyPSScriptRoot -Force | Out-Null } -$p = @($p[0], $MyPSScrtipRoot) + $($p | Select-Object -Skip 1) +$p = @($p[0], $MyPSScriptRoot) + $($p | Select-Object -Skip 1) $env:PATH = $p -join $PathEnvDelimiter -Get-Command Reload-MyAliases -ErrorAction SilentlyContinue | ForEach-Object { Reload-MyAliases } +Get-Command Reload-MyScripts -ErrorAction SilentlyContinue | ForEach-Object { . $_.Name } ``` diff --git a/Reload-MyAliases.ps1 b/Reload-MyScripts.ps1 similarity index 66% rename from Reload-MyAliases.ps1 rename to Reload-MyScripts.ps1 index e1015b0..fad2342 100644 --- a/Reload-MyAliases.ps1 +++ b/Reload-MyScripts.ps1 @@ -1,11 +1,13 @@ [CmdletBinding(SupportsShouldProcess)]param() $local:myAliases = [ordered]@{} -$myAliases.sudo = 'Invoke-MySudo' +$myAliases.sudo = 'Invoke-Sudo' $myAliases.vi = 'Edit-TextFile' $myAliases.vim = 'Edit-TextFile' $myAliases.nvim = 'Edit-TextFile' $myAliases.nvim = 'Edit-TextFile' +$myAliases.l = 'ls.ps1' +$myAliases.ll = 'ls.ps1' ####################################################################### @@ -13,7 +15,7 @@ $local:IsVerbose = [bool]($PSBoundParameters['Verbose']) $local:MyAliasScope = 1 -$local:oldAliases = Get-MyAliases +$local:oldAliases = . Get-MyAliases $oldAliases = Get-Alias -Scope $MyAliasScope | Where-Object Name -in $($oldAliases.Name + $myAliases.Keys) @@ -22,7 +24,7 @@ if( $oldAliases -and $IsVerbose ) { Write-Verbose "Removing: $($oldAliases.Name -join ', ')" } $oldAliases | Remove-Alias -Scope $MyAliasScope -Get-ChildItem (Join-Path $MyPSScrtipRoot '*.ps1') | +Get-ChildItem (Join-Path $MyPSScriptRoot '*.ps1') | ForEach-Object { Set-Alias $($_.BaseName) $_.FullName -Scope $MyAliasScope } @@ -30,3 +32,6 @@ Get-ChildItem (Join-Path $MyPSScrtipRoot '*.ps1') | foreach( $local:alias in $myAliases.Keys ) { Set-Alias -Name $alias -Value $myAliases[$alias] -Description '#MyAlias' -Scope $MyAliasScope } + +if( $(. Get-ScopeDepth) -gt 0 ) { Write-Host -ForegroundColor Red "Try sourcing Reload-MyScripts instead of just running it" } +Get-ChildItem $(Join-Path $MyPSScriptRoot profile.d) -Filter '*.ps1' | ForEach-Object { ". '$($_.FullName)';" } | Invoke-Expression diff --git a/profile.d/FunctionName.class.ps1 b/profile.d/FunctionName.class.ps1 new file mode 100644 index 0000000..9e51fc4 --- /dev/null +++ b/profile.d/FunctionName.class.ps1 @@ -0,0 +1,21 @@ +class FunctionName: System.Management.Automation.IValidateSetValuesGenerator { + static [string[]] _GetValidValues([string]$wordToComplete,[bool]$Strict) { + $local:possibleValues = Get-Command -Type Function | Select-Object -ExpandProperty Name + return $(Get-PossibleArguments -WordToComplete $wordToComplete -FullValueSet $possibleValues -Strict:$Strict ); + } + static [String[]] _GetValidValues([string]$wordToComplete,[switch]$Strict) { + return $(Get-PossibleArguments -WordToComplete $wordToComplete -FullValueSet $(Get-Command -Type Function | Select-Object -ExpandProperty Name) -Strict:$Strict) +# $local:possibleValues = +# if( $wordToComplete ) { +# $possibleValues = $possibleValues | Where-Object { $_ -match $wordToComplete } +# if( -not $strict -and ($wordToComplete -notin $possibleValues) ) { +# $possibleValues = $( $wordToComplete; $possibleValues ) +# } +# } +# return $possibleValues + } + + [String[]] GetValidValues() { + return [FunctionName]::_GetValidValues('',$true) + } +} diff --git a/profile.d/MyScript.class.ps1 b/profile.d/MyScript.class.ps1 new file mode 100644 index 0000000..aab3df9 --- /dev/null +++ b/profile.d/MyScript.class.ps1 @@ -0,0 +1,15 @@ +class MyScript : System.Management.Automation.IValidateSetValuesGenerator { + static [string[]] _GetValidValues([string]$wordToComplete,[bool]$Strict) { + $local:possibleValues = $( + Get-ChildItem $global:MyPSScriptRoot -Filter '*.ps1' -Recurse | + Select-Object -ExpandProperty FullName | ForEach-Object { + $_ -replace '\.ps1$','' -replace "$($MyPSScriptRoot -replace '\\',"\\")[/\\]",'' + } + ) + return $(Get-PossibleArguments -WordToComplete $wordToComplete -FullValueSet $possibleValues -Strict:$Strict ); + } + + [String[]] GetValidValues() { + return [MyScript]::_GetValidValues('',$true) + } +}