{%- let SECTION = "# =============================================================================\n#" -%} {%- let NOT_CONFIGURED = "# -- not configured --" -%} {{ SECTION }} # Utility functions for zoxide. # # Invoke zoxide, safely escaping the arguments # PowerShell escapes command line arguments following the cmd.exe way instead of the C++/Rust way by default function zoxide { $startInfo = [System.Diagnostics.ProcessStartInfo]::new("zoxide") $startInfo.StandardOutputEncoding = [System.Text.Encoding]::UTF8 $startInfo.RedirectStandardOutput = $true $startInfo.RedirectStandardError = $true $startInfo.CreateNoWindow = $true $startInfo.UseShellExecute = $false if ($startInfo.ArgumentList.Add) { # PowerShell 6+ uses .NET 5+ and supports the ArgumentList property # which bypasses the need for manually escaping the argument list into # a command string. foreach ($arg in $args) { $startInfo.ArgumentList.Add($arg) } } else { # Build an arguments string which follows the C++ command-line argument quoting rules # See: https://docs.microsoft.com/en-us/previous-versions//17w5ykft(v=vs.85)?redirectedfrom=MSDN $escaped = $args | ForEach-Object { $s = $_ -Replace '(\\+)"','$1$1"'; # Escape backslash chains immediately preceeding quote marks. $s = $s -Replace '(\\+)$','$1$1'; # Escape backslash chains immediately preceeding the end of the string. $s = $s -Replace '"','\"'; # Escape quote marks. "`"$s`"" # Quote the argument. } $startInfo.Arguments = $escaped -Join ' '; } $process = [System.Diagnostics.Process]::Start($startInfo) # stderr isn't displayed with this style of invocation # Manually write it to console $stderr = $process.StandardError.ReadToEnd().Trim() if ($stderr -ne '') { # Write-Error doesn't work here $host.ui.WriteErrorLine($stderr) } $process.StandardOutput.ReadToEnd() } # pwd based on the value of _ZO_RESOLVE_SYMLINKS. function __zoxide_pwd { $(Get-Location).Path } # cd + custom logic based on the value of _ZO_ECHO. function __zoxide_cd($dir) { Set-Location $dir -ea Stop {%- if echo %} __zoxide_pwd {%- endif %} } {{ SECTION }} # Hook configuration for zoxide. # # Hook to add new entries to the database. function __zoxide_hook { zoxide add $(__zoxide_pwd) } # Initialize hook. if ($__zoxide_hooked -ne '1') { $__zoxide_hooked = '1' {%- match hook %} {%- when Hook::None %} {{ NOT_CONFIGURED }} {%- when Hook::Prompt %} $__zoxide_prompt_old = $function:prompt function prompt { $null = __zoxide_hook & $__zoxide_prompt_old } {%- when Hook::Pwd %} if ($PSVersionTable.PSVersion.Major -ge 6) { $ExecutionContext.InvokeCommand.LocationChangedAction = { $null = __zoxide_hook } } else { Write-Error ("`n" + "zoxide: PWD hooks are not supported below PowerShell 6.`n" + " Use 'zoxide init powershell --hook prompt' instead.") } {%- endmatch %} } {{ SECTION }} # When using zoxide with --no-aliases, alias these internal functions as # desired. # # Jump to a directory using only keywords. function __zoxide_z { if ($args.Length -eq 0) { __zoxide_cd ~ } elseif ($args.Length -eq 1 -and $args[0] -eq '-') { __zoxide_cd - } elseif ($args.Length -eq 1 -and ( Test-Path $args[0] -PathType Container) ) { __zoxide_cd $args[0] } else { $__zoxide_result = zoxide query -- @args if ($LASTEXITCODE -eq 0) { __zoxide_cd $__zoxide_result } } } # Jump to a directory using interactive search. function __zoxide_zi { $__zoxide_result = zoxide query -i -- @args if ($LASTEXITCODE -eq 0) { __zoxide_cd $__zoxide_result } } {{ SECTION }} # Convenient aliases for zoxide. Disable these using --no-aliases. # {%- match cmd %} {%- when Some with (cmd) %} Set-Alias {{cmd}} __zoxide_z Set-Alias {{cmd}}i __zoxide_zi {%- when None %} {{ NOT_CONFIGURED }} {%- endmatch %} {{ SECTION }} # To initialize zoxide with PowerShell, add the following line to your # PowerShell configuration file (the location is stored in $profile): # # Invoke-Expression (& { $hook = if ($PSVersionTable.PSVersion.Major -ge 6) { 'pwd' } else { 'prompt' } (zoxide init powershell --hook $hook) -join "`n" })