DevEnv.psm1
function getProjectPath { if ($null -ne $_DEVENV_PROJECT_PATH -and (Test-Path $_DEVENV_PROJECT_PATH)) { return $_DEVENV_PROJECT_PATH } else { $project_dir = (Get-Location).Path if (-not (Test-Path (Join-Path $project_dir ".pcode"))) { return $null } return $project_dir } } function convertToHashtable { param ($suspect_object) $conv_hash_table = @{} foreach ($property in $suspect_object.PSObject.Properties) { if ($property.Value -is [psobject]) { $conv_hash_table[$property.Name] = convertToHashtable $Property.Value } else { # Null values are placeholders in settings, not used if ($null -ne $property.Value) { $conv_hash_table[$property.Name] = $Property.Value } } } $conv_hash_table } function getProjectSettings { # Attempt to pull settings file from project template $project = [io.path]::Combine((getProjectPath), ".pcode", ".settings.json") if (Test-Path -Path $project) { $project_settings = convertToHashtable( (Get-Content $project -Encoding UTF8) | ConvertFrom-Json) return $project_settings } else { # Fallback to default settings $defaults = Join-Path (Split-Path -Parent $PSCommandPath) -ChildPath defaults.json $default_settings = convertToHashtable( (Get-Content $defaults -Encoding UTF8) | ConvertFrom-Json) return $default_settings } } function loadProjectSettings { New-Variable -Scope global -Name _DEVENV_SETTINGS -Force -Value (getProjectSettings) } function preservePrompt { function global:_DEVENV_ORIG_PROMPT { "" } $function:_DEVENV_ORIG_PROMPT = $function:global:prompt } function updatePwshPrompt { function global:_DEVENV_OLD_PROMPT { "" } $function:_DEVENV_OLD_PROMPT = $function:global:prompt function global:_DEVENV_PROMPT { if ($null -eq $_DEVENV_PROJECT_PATH) { $function:prompt = $function:_DEVENV_ORIG_PROMPT return } if ($null -ne $_DEVENV_PROMPT_FIRED) { return & $function:_DEVENV_ORIG_PROMPT } else { New-Variable -Name _DEVENV_PROMPT_FIRED -Force -Value $true $curr_loc = [string]($executionContext.SessionState.Path.CurrentLocation) $in_project = $curr_loc.StartsWith($_DEVENV_PROJECT_PATH) if (-not $in_project) { Exit-Code $false | Out-Null $function:prompt = $function:_DEVENV_ORIG_PROMPT return & $function:_DEVENV_ORIG_PROMPT } $prompt_settings = $_DEVENV_SETTINGS.prompt Write-Host -nonewline @prompt_settings return & $function:_DEVENV_OLD_PROMPT } } function global:prompt { return & $function:_DEVENV_PROMPT } } function createWorkspaceAlias { Param([System.Array] $file_list) foreach ($alias_file in $file_list) { New-Alias $alias_file.BaseName $alias_file.FullName -Scope Global -Force $user_str = "Workspace alias " + ($alias_file).BaseName + " added" Write-Output $user_str } } function removeWorkspaceAlias { Param([System.Array] $file_list) foreach ($alias_file in $file_list) { Remove-Item "alias:\$($alias_file.BaseName)" $user_str = "Workspace alias " + ($alias_file).BaseName + " removed" Write-Output $user_str } } function aliasFileList { $project_dir = getProjectPath if (-not $project_dir) { return $null } $files = (Get-ChildItem -Path ([io.path]::Combine($project_dir, ".pcode")) -File ) | Where-Object { $_.Name -notlike ".*" -and $_.Name -like "*.ps1"} return $files } function getProjectScriptPath { Param([string] $script) return [io.path]::Combine((getProjectPath), ".pcode", $script) } function execProjectScript { param( [Parameter(Mandatory=$true)][string] $script, [Parameter(Mandatory=$false)][string] $option = "" ) $script_filepath = getProjectScriptPath $script if (Test-Path $script_filepath) { . $script_filepath $option } else { throw "Did not find script file {0} in .pcode" -f ($script) } } function getEnvVar { Param([string] $env_var) return [Environment]::GetEnvironmentVariable($env_var) } function templateDirs { param( [Parameter(Mandatory=$false)][bool] $user_template_dirs = $true ) $template_dirs = @() # Path where module is installed (varies based on how user installed it) $module_path = Get-Variable PSScriptRoot -Scope Script -ValueOnly $template_dirs += $module_path if ($user_template_dirs) { if (Test-Path (Join-Path (getEnvVar "APPDATA") "PSDevEnv")) { $template_dirs += (Join-Path (getEnvVar "APPDATA") "PSDevEnv") } } return $template_dirs } function userTraversingDownTree { param( [Parameter(Mandatory=$true)][string] $curr_loc ) # Returns true if the user has either just started in the directory # or is traversing down the directory tree if ($null -eq $_DEVENV_DIR_HIST) { New-Variable -Scope global -Name _DEVENV_DIR_HIST -Value $curr_loc } else { $last_loc = $_DEVENV_DIR_HIST New-Variable -Scope global -Name _DEVENV_DIR_HIST -Value $curr_loc -Force if ($last_loc.StartsWith($curr_loc)) { return $false } } return $true } function Get-Code { # Returns the current code template path param( [Parameter(Mandatory=$false)][string] $code_type, [Parameter(Mandatory=$false)][bool] $use_user_templates = $true ) $code_type = $code_type.ToLower() $pcode_dirs = @() foreach ($template in (templateDirs $use_user_templates)) { $pcode_dirs += (Get-ChildItem -Path $template -Directory | Where-Object Name -like ".pcode_*") } if ($pcode_dirs.count -lt 1) { throw "Could not find template directories (.pcode_*) in the expected locations:\n{0}" -f ( (templateDirs $use_user_templates) -Join "`n" ) } $pcode_pref_dirs = @{} foreach ($pcode in $pcode_dirs) { $pcode_pref_dirs[$pcode.Name] = $pcode } $match = $pcode_pref_dirs.GetEnumerator() | Where-Object -Property key -Match ".pcode_$($code_type)" if ($match.count -lt 1) { throw "Could not find a match for '{0}'`nThese options are available:`n{1}" -f ( $code_type, (($pcode_pref_dirs.Keys-replace ".pcode_") -Join "`n")) } if ($match.count -gt 1) { $exact = $pcode_pref_dirs.GetEnumerator() | Where-Object -Property key -Eq ".pcode_$($code_type)" if ($exact.count -eq 1) { return $exact.Value } # Determine if there is an exact match throw "Found multiple matches, use one of these:`n{0}" -f ( ($match.Name -replace ".pcode_") -Join "`n") } return $match.Value } function Set-Code { param([Parameter(Mandatory=$false)][string] $code_type) # Creates Code template for user, copies over defaults # TODO for the future: # -Force - Force copying over the defaults if the directory already exists # -Empty - Only create the directory if it does not exist, do not copy items # Also should think about items that do not have existing templates # Create the directory if it does not exist, otherwise error $pcode_user_path = New-Item -Path ( [IO.Path]::Combine((getEnvVar APPDATA), "PSDevEnv", ".pcode_$($code_type)")) -ItemType Directory # See if there is a default template to copy over try { $match = Get-Code -code_type $code_type -use_user_templates $false } catch { $match = $null } if ($match) { # Copy the template over to the project Write-Information "Copying default project template over..." Copy-Item -Path "$($match.FullName)\*" -Destination "$($pcode_user_path.FullName)" -Recurse -Force } return $pcode_user_path } function New-Code { param( [Parameter(Mandatory=$true)][string] $code_type, [Parameter(Mandatory=$false)][string] $option = "" ) $match = Get-Code($code_type) # Copy the template over to the project Write-Output "Copying project template over..." Copy-Item -Path (Join-Path $match.FullName "*") -Destination . -Recurse -Force loadProjectSettings # Start the initialization script for the environment execProjectScript "..init.ps1" -option $option # Enter the new environment Enter-Code -update_prompt $true } function Enter-Code { param( [Parameter(Mandatory=$false)][bool] $update_prompt = $true, [Parameter(Mandatory=$false)][bool] $raise_on_failure = $false, [Parameter(Mandatory=$false)][switch] $auto_entry ) if ($auto_entry.IsPresent) { $curr_loc = [string]($executionContext.SessionState.Path.CurrentLocation) if (-not (userTraversingDownTree $curr_loc)) { return } } # Project is already setup or entrant script is not available if (($null -ne $_DEVENV_PROJECT_PATH) -or -not (Test-Path (getProjectScriptPath "..enter.ps1"))) { return } # Add project path to Global Project Path variable $project_dir = getProjectPath if (-not $project_dir) { return } loadProjectSettings New-Variable -Scope global -Name _DEVENV_PROJECT_PATH -Force -Value $project_dir try { preservePrompt # Update the prompt if ($update_prompt) { updatePwshPrompt } # Run enterance script execProjectScript("..enter.ps1") if ($update_prompt) { updatePwshPrompt } # Create project aliases createWorkspaceAlias(aliasFileList) } catch { if ($raise_on_failure) { throw $_ } } } function Exit-Code { param( [Parameter(Mandatory=$false)][bool] $raise_on_failure = $true ) try { # Run exit script execProjectScript("..exit.ps1") # Remove project aliases removeWorkspaceAlias(aliasFileList) } catch { if ($raise_on_failure) { throw $_ } } finally { # Reset Global Project Path variable New-Variable -Scope global -Name _DEVENV_PROJECT_PATH -Force -Value $null } } |