File Coverage

blib/lib/App/Rakubrew/Shell/PowerShell.pm
Criterion Covered Total %
statement 29 63 46.0
branch 1 16 6.2
condition 0 6 0.0
subroutine 10 17 58.8
pod 0 8 0.0
total 40 110 36.3


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