123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271 |
- param([parameter(Position=0,Mandatory=$false)] [Hashtable] $CondaModuleArgs=@{})
- # Defaults from before we had arguments.
- if (-not $CondaModuleArgs.ContainsKey('ChangePs1')) {
- $CondaModuleArgs.ChangePs1 = $True
- }
- ## ENVIRONMENT MANAGEMENT ######################################################
- <#
- .SYNOPSIS
- Obtains a list of valid conda environments.
- .EXAMPLE
- Get-CondaEnvironment
- .EXAMPLE
- genv
- #>
- function Get-CondaEnvironment {
- [CmdletBinding()]
- param();
- begin {}
- process {
- # NB: the JSON output of conda env list does not include the names
- # of each env, so we need to parse the fragile output instead.
- & $Env:CONDA_EXE $Env:_CE_M $Env:_CE_CONDA env list | `
- Where-Object { -not $_.StartsWith("#") } | `
- Where-Object { -not $_.Trim().Length -eq 0 } | `
- ForEach-Object {
- $envLine = $_ -split "\s+";
- $Active = $envLine[1] -eq "*";
- [PSCustomObject] @{
- Name = $envLine[0];
- Active = $Active;
- Path = if ($Active) {$envLine[2]} else {$envLine[1]};
- } | Write-Output;
- }
- }
- end {}
- }
- <#
- .SYNOPSIS
- Activates a conda environment, placing its commands and packages at
- the head of $Env:PATH.
- .EXAMPLE
- Enter-CondaEnvironment base
- .EXAMPLE
- etenv base
- .NOTES
- This command does not currently support activating environments stored
- in a non-standard location.
- #>
- function Enter-CondaEnvironment {
- [CmdletBinding()]
- param(
- [Parameter(Mandatory=$false)][switch]$Stack,
- [Parameter(Position=0)][string]$Name
- );
- begin {
- If ($Stack) {
- $activateCommand = (& $Env:CONDA_EXE $Env:_CE_M $Env:_CE_CONDA shell.powershell activate --stack $Name | Out-String);
- } Else {
- $activateCommand = (& $Env:CONDA_EXE $Env:_CE_M $Env:_CE_CONDA shell.powershell activate $Name | Out-String);
- }
- Write-Verbose "[conda shell.powershell activate $Name]`n$activateCommand";
- Invoke-Expression -Command $activateCommand;
- }
- process {}
- end {}
- }
- <#
- .SYNOPSIS
- Deactivates the current conda environment, if any.
- .EXAMPLE
- Exit-CondaEnvironment
- .EXAMPLE
- exenv
- #>
- function Exit-CondaEnvironment {
- [CmdletBinding()]
- param();
- begin {
- $deactivateCommand = (& $Env:CONDA_EXE $Env:_CE_M $Env:_CE_CONDA shell.powershell deactivate | Out-String);
- # If deactivate returns an empty string, we have nothing more to do,
- # so return early.
- if ($deactivateCommand.Trim().Length -eq 0) {
- return;
- }
- Write-Verbose "[conda shell.powershell deactivate]`n$deactivateCommand";
- Invoke-Expression -Command $deactivateCommand;
- }
- process {}
- end {}
- }
- ## CONDA WRAPPER ###############################################################
- <#
- .SYNOPSIS
- conda is a tool for managing and deploying applications, environments
- and packages.
- .PARAMETER Command
- Subcommand to invoke.
- .EXAMPLE
- conda install toolz
- #>
- function Invoke-Conda() {
- # Don't use any explicit args here, we'll use $args and tab completion
- # so that we can capture everything, INCLUDING short options (e.g. -n).
- if ($Args.Count -eq 0) {
- # No args, just call the underlying conda executable.
- & $Env:CONDA_EXE $Env:_CE_M $Env:_CE_CONDA;
- }
- else {
- $Command = $Args[0];
- if ($Args.Count -ge 2) {
- $OtherArgs = $Args[1..($Args.Count - 1)];
- } else {
- $OtherArgs = @();
- }
- switch ($Command) {
- "activate" {
- Enter-CondaEnvironment @OtherArgs;
- }
- "deactivate" {
- Exit-CondaEnvironment;
- }
- default {
- # There may be a command we don't know want to handle
- # differently in the shell wrapper, pass it through
- # verbatim.
- & $Env:CONDA_EXE $Env:_CE_M $Env:_CE_CONDA $Command @OtherArgs;
- }
- }
- }
- }
- ## TAB COMPLETION ##############################################################
- # We borrow the approach used by posh-git, in which we override any existing
- # functions named TabExpansion, look for commands we can complete on, and then
- # default to the previously defined TabExpansion function for everything else.
- if (Test-Path Function:\TabExpansion) {
- # Since this technique is common, we encounter an infinite loop if it's
- # used more than once unless we give our backup a unique name.
- Rename-Item Function:\TabExpansion CondaTabExpansionBackup
- }
- function Expand-CondaEnv() {
- param(
- [string]
- $Filter
- );
- $ValidEnvs = Get-CondaEnvironment;
- $ValidEnvs `
- | Where-Object { $_.Name -like "$filter*" } `
- | ForEach-Object { $_.Name } `
- | Write-Output;
- $ValidEnvs `
- | Where-Object { $_.Path -like "$filter*" } `
- | ForEach-Object { $_.Path } `
- | Write-Output;
- }
- function Expand-CondaSubcommands() {
- param(
- [string]
- $Filter
- );
- $ValidCommands = Invoke-Conda shell.powershell commands;
- # Add in the commands defined within this wrapper, filter, sort, and return.
- $ValidCommands + @('activate', 'deactivate') `
- | Where-Object { $_ -like "$Filter*" } `
- | Sort-Object `
- | Write-Output;
- }
- function TabExpansion($line, $lastWord) {
- $lastBlock = [regex]::Split($line, '[|;]')[-1].TrimStart()
- switch -regex ($lastBlock) {
- # Pull out conda commands we recognize first before falling through
- # to the general patterns for conda itself.
- "^conda activate (.*)" { Expand-CondaEnv $lastWord; break; }
- "^etenv (.*)" { Expand-CondaEnv $lastWord; break; }
- # If we got down to here, check arguments to conda itself.
- "^conda (.*)" { Expand-CondaSubcommands $lastWord; break; }
- # Finally, fall back on existing tab expansion.
- default {
- if (Test-Path Function:\CondaTabExpansionBackup) {
- CondaTabExpansionBackup $line $lastWord
- }
- }
- }
- }
- ## PROMPT MANAGEMENT ###########################################################
- <#
- .SYNOPSIS
- Modifies the current prompt to show the currently activated conda
- environment, if any.
- .EXAMPLE
- Add-CondaEnvironmentToPrompt
- Causes the current session's prompt to display the currently activated
- conda environment.
- #>
- if ($CondaModuleArgs.ChangePs1) {
- # We use the same procedure to nest prompts as we did for nested tab completion.
- if (Test-Path Function:\prompt) {
- Rename-Item Function:\prompt CondaPromptBackup
- } else {
- function CondaPromptBackup() {
- # Restore a basic prompt if the definition is missing.
- "PS $($executionContext.SessionState.Path.CurrentLocation)$('>' * ($nestedPromptLevel + 1)) ";
- }
- }
- function global:prompt() {
- if ($Env:CONDA_PROMPT_MODIFIER) {
- $Env:CONDA_PROMPT_MODIFIER | Write-Host -NoNewline
- }
- CondaPromptBackup;
- }
- }
- ## ALIASES #####################################################################
- New-Alias conda Invoke-Conda -Force
- New-Alias genv Get-CondaEnvironment -Force
- New-Alias etenv Enter-CondaEnvironment -Force
- New-Alias exenv Exit-CondaEnvironment -Force
- ## EXPORTS ###################################################################
- Export-ModuleMember `
- -Alias * `
- -Function `
- Invoke-Conda, `
- Get-CondaEnvironment, `
- Enter-CondaEnvironment, Exit-CondaEnvironment, `
- TabExpansion, prompt
|