File Coverage

blib/lib/App/Rakubrew/Shell/PowerShell.pm
Criterion Covered Total %
statement 29 62 46.7
branch 1 14 7.1
condition 0 6 0.0
subroutine 10 17 58.8
pod 0 8 0.0
total 40 107 37.3


line stmt bran cond sub pod time code
1             package App::Rakubrew::Shell::PowerShell;
2 1     1   6 use App::Rakubrew::Shell;
  1         2  
  1         44  
3             our @ISA = "App::Rakubrew::Shell";
4 1     1   5 use strict;
  1         2  
  1         21  
5 1     1   6 use warnings;
  1         2  
  1         22  
6 1     1   15 use 5.010;
  1         3  
7              
8 1     1   5 use App::Rakubrew::Variables;
  1         2  
  1         167  
9 1     1   7 use App::Rakubrew::Tools;
  1         2  
  1         106  
10 1     1   7 use App::Rakubrew::VersionHandling;
  1         2  
  1         123  
11 1     1   6 use App::Rakubrew::Build;
  1         3  
  1         30  
12 1     1   5 use App::Rakubrew::Config;
  1         2  
  1         708  
13              
14             # https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_scopes?view=powershell-6
15             # https://stackoverflow.com/questions/6766722/how-to-modify-parent-scope-variable-using-powershell
16             # https://superuser.com/questions/886951/run-powershell-script-when-you-open-powershell
17             # https://www.computerperformance.co.uk/powershell/profile-ps1/
18              
19             =pod
20              
21             WARNING:
22             Setting PATH to a string longer than 2048 chars (4096 on newer systems) can cause the
23             PATH to be truncated, your PATH being set to the empty string and only become available
24             again upon reboot and in the worst case cause your system to not boot anymore.
25             See https://web.archive.org/web/20190519191717/https://software.intel.com/en-us/articles/limitation-to-the-length-of-the-system-path-variable
26              
27             This problem is smaller for us, because we only modify PATH in the current console, never globally.
28              
29             =cut
30              
31             sub supports_hooking {
32 0     0 0 0 my $self = shift;
33 0         0 1;
34             }
35              
36             sub install_note {
37 1     1 0 319 my $text = <
38             Load $brew_name automatically in PowerShell by adding
39              
40             . "$brew_exec" init PowerShell | Out-String | Invoke-Expression
41              
42             to your PowerShell profile. (Note the "." at the beginning!)
43             This can be easily done using:
44              
45             New-Item -Path (Split-Path \$PROFILE) -ItemType "Directory" -Force
46             Add-Content -Force -Path \$PROFILE -Value '. "$brew_exec" init PowerShell | Out-String | Invoke-Expression'
47              
48             (Note that the above does *not* enable auto-loading in CMD, that needs a
49             separate installation procedure. Call `$brew_exec init` in a CMD window for
50             respective installation instructions.)
51             EOT
52              
53 1 50       8 if ($prefix =~ / /) {
54 0         0 $text .= <
55              
56             =================================== WARNING ==================================
57              
58             rakubrews home directory is currently
59              
60             $prefix
61              
62             That folder contains spaces. This will break building rakudos as the build
63             system currently doesn't work in such a path. You can work around this problem
64             by changing that folder to a directory without spaces. Do so by putting
65              
66             \$Env:RAKUBREW_HOME = "/some/folder/without/space/rakubrew"
67              
68             in your profile file *before* the other code.
69             EOW
70             }
71 1         18 return $text;
72             }
73              
74             sub get_init_code {
75 0     0 0   my $self = shift;
76 0           my $path = $ENV{PATH};
77 0           $path = $self->clean_path($path);
78 0 0         if (get_brew_mode() eq 'env') {
79 0           my $version = get_global_version();
80 0 0 0       if ($version && $version ne 'system' && !is_version_broken($version)) {
      0        
81 0           $path = join(';', get_bin_paths($version), $path);
82             }
83             }
84             else { # get_brew_mode() eq 'shim'
85 0           $path = join(';', $shim_dir, $path);
86             }
87 0           return <
88             \$Env:PATH = "$path"
89             Function $brew_name {
90             # TODO: In PowerShell functions do not have return codes. Thus we can not forward the underlying return code.
91             # For now we just throw if the actual rakubrew has a returncode != 0. Maybe come up with a better way?
92             . "$brew_exec" internal_hooked PowerShell \$args
93             if (\$LASTEXITCODE -ne 0) {
94             Throw "Rakubrew failed with exitcode \$LASTEXITCODE"
95             }
96             \$cmd = . "$brew_exec" internal_shell_hook PowerShell post_call_eval \$args | Out-String
97             if (\$cmd) {
98             Invoke-Expression -Command \$cmd
99             }
100             }
101             # TODO: \$PSVersionTable.PSVersion is only available from PowerShell 2.0 onward. Either accept that this fails on PS 1 or find a way to guard against that.
102             if (\$PSVersionTable.PSVersion.Major -ge 5) {
103             Register-ArgumentCompleter -Native -CommandName $brew_name -ScriptBlock {
104             param(\$commandName, \$argumentString, \$position)
105             \$completions = . "$brew_exec" internal_shell_hook PowerShell completions "\$position" "\$argumentString" | Out-String
106             \$completions = \$completions.trim('\n').Split(' ')
107             \$completions | ForEach-Object {
108             [System.Management.Automation.CompletionResult]::new(\$_, \$_, 'ParameterValue', \$_)
109             }
110             }
111             }
112             EOT
113             }
114              
115             sub post_call_eval {
116 0     0 0   my $self = shift;
117 0           $self->print_shellmod_code(@_);
118             }
119              
120             sub get_path_setter_code {
121 0     0 0   my $self = shift;
122 0           my $path = shift;
123 0           return "\$Env:PATH = \"$path\"";
124             }
125              
126             sub get_shell_setter_code {
127 0     0 0   my $self = shift;
128 0           my $version = shift;
129 0           return "Set-Variable -Name $env_var -Value \"$version\" -Scope Global";
130             }
131              
132             sub get_shell_unsetter_code {
133 0     0 0   my $self = shift;
134 0           return "Remove-Variable -Name $env_var -Scope Global";
135             }
136              
137             sub completions {
138 0     0 0   my $self = shift;
139 0           my $position = shift;
140 0           my $argumentString = join ' ', @_;
141              
142             # Check if the cursor is starting a new word (preceding space).
143 0 0         my $newWord = $position > length($argumentString) ? 1
    0          
144             : substr($argumentString, $position - 1, $position) eq ' ' ? 1
145             : 0;
146              
147             # Cut off everything after cursor position.
148 0           $argumentString = substr($argumentString, 0, $position);
149              
150             # Chop off trailing space.
151 0 0         $argumentString = chop($argumentString) if substr($argumentString, 0, length($argumentString) - 1) eq ' ';
152              
153             # Remove command name and trailing space from arguments.
154 0           $argumentString =~ s/(^|.*\W)$brew_name(\.bat|\.exe)? ?//;
155              
156 0           my @words = split ' ', $argumentString;
157 0 0         my $index = @words - 1 + ($newWord ? 1 : 0);
158              
159 0           my @completions = $self->get_completions($index, @words);
160 0           say join(' ', @completions);
161             }
162              
163             1;