Skip to content

Commit

Permalink
Add tab-completion for powershell
Browse files Browse the repository at this point in the history
  • Loading branch information
kblohm committed Oct 28, 2018
1 parent 484c953 commit bd74f3b
Show file tree
Hide file tree
Showing 6 changed files with 293 additions and 2 deletions.
2 changes: 1 addition & 1 deletion bash-completion/README.md → completion/bash/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ fi

## Install completion for FAKE
```bash
cd bash-completion
cd completion/bash
./install.sh
```
File renamed without changes.
File renamed without changes.
229 changes: 229 additions & 0 deletions completion/powershell/posh-fake.psm1
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
using namespace System.Management.Automation
using namespace System.Management.Automation.Language


function New-CommandResult {
param (
[Parameter(Mandatory)]
[string]$CompletionText,
[string]$ToolTip = $CompletionText,
[string]$ListItemText = $CompletionText
)

New-Object CompletionResult $CompletionText, $ListItemText, Command, $ToolTip
}

function New-TextResult {
param (
[Parameter(Mandatory)]
[string]$CompletionText,
[string]$ToolTip = $CompletionText,
[string]$ListItemText = $CompletionText
)

New-Object CompletionResult $CompletionText, $ListItemText, Text, $ToolTip
}

function New-ParameterNameResult {
param (
[Parameter(Mandatory)]
[string]$CompletionText,
[string]$ToolTip = $CompletionText,
[string]$ListItemText = $CompletionText,
[string[]]$Aliases = $null
)
New-Object CompletionResult $CompletionText, $ListItemText, ParameterName, $ToolTip
if ($Aliases) {
$Aliases | ForEach-Object { New-Object CompletionResult $_, $ListItemText, ParameterName, $ToolTip }
}
}

function Get-Targets {
Param([string[]]$fakeResult)
$startIndex = $fakeResult.IndexOf('The following targets are available:')
$endIndex = $fakeResult.IndexOf('Performance:')
if ($startIndex -ge 0 -and $endIndex -ge $startIndex) {
for ($index = $startIndex + 1; $index -lt $endIndex; $index++) {
$target = $fakeResult[$index].Trim()
New-TextResult $target
}
}
}

function Get-BuildTargets {
Param($wordToComplete, $commandAst, $cursorPosition)
$elements = $commandAst.CommandElements
for ($index = 0; $index -lt $elements.Count; $index++) {
if ($elements[$index].Value -like '--script' -or $elements[$index].Value -like '-f') {
$scriptName = $elements[$index + 1].Value
$extension = [System.IO.Path]::GetExtension($scriptName)
if ($extension -like '.fsx') {
return Get-Targets(fake build --script $scriptName --list)
}
return @()
}
}
Get-Targets(fake build --list)
}

function Get-RunTargets {
param($wordToComplete, $commandAst, $cursorPosition)
$elements = $commandAst.CommandElements
for ($index = 0; $index -lt $elements.Count; $index++) {
if ($elements[$index].Value -like 'run') {
$scriptName = $elements[$index + 1].Value
$extension = [System.IO.Path]::GetExtension($scriptName)
if ($extension -like '.fsx') {
return Get-Targets(fake run $scriptName --list)
}
}
}
@()
}


$fakeBuild = {
param($wordToComplete, $prev, $commandAst, $cursorPosition)

switch ($prev) {
# file completion
'--script' {return @()}
'-f' {return return @()}
# target completion
'--target' { return Get-BuildTargets $wordToComplete $commandAst $cursorPosition}
'-t' { return Get-BuildTargets $wordToComplete $commandAst $cursorPosition}
'target' { return Get-BuildTargets $wordToComplete $commandAst $cursorPosition}
}

@(
New-CommandResult 'target' 'Run the given target.'
New-ParameterNameResult '--help' 'Show help.' -Aliases '-h'
New-ParameterNameResult '--debug' 'Debug the script.' -Aliases '-d'
New-ParameterNameResult '--nocache' 'Disable fake cache for this run.' '-n'
New-ParameterNameResult '--partial-restore' 'Only restore the required group instead of a full restore.' -Aliases '-p'
New-ParameterNameResult '--fsiargs' 'Arguments passed to the f# interactive.'
New-ParameterNameResult '--script' 'The script to execute (defaults to `build.fsx`).' -Aliases '-f'
New-ParameterNameResult '--target' "Run the given target (ignored if positional argument 'target' is given)." -Aliases '-t'
New-ParameterNameResult '--list' 'List all available targets.'
New-ParameterNameResult '--single-target' 'Run only the specified target.' -Aliases '-s'
New-ParameterNameResult '--parallel' 'Run parallel with the given number of tasks.' -Aliases '-p'
New-ParameterNameResult '--environment-variable' "Set an environment variable. Use 'key=val'." -Aliases '-e'
)
}

$fakeRun = {
param($wordToComplete, $prev, $commandAst, $cursorPosition)

switch ($prev) {
# file completion
'run' {return return @()}
# target completion
'--target' { return Get-RunTargets $wordToComplete $commandAst $cursorPosition}
'-t' { return Get-RunTargets $wordToComplete $commandAst $cursorPosition}
}
@(
New-CommandResult 'target' 'Run the given target.'
New-ParameterNameResult '--help' 'Show help.' -Aliases '-h'
New-ParameterNameResult '--debug' 'Debug the script.' -Aliases '-d'
New-ParameterNameResult '--nocache' 'Disable fake cache for this run.' '-n'
New-ParameterNameResult '--partial-restore' 'Only restore the required group instead of a full restore.' -Aliases '-p'
New-ParameterNameResult '--fsiargs' 'Arguments passed to the f# interactive.'
New-ParameterNameResult '--target' "Run the given target (ignored if positional argument 'target' is given)." -Aliases '-t'
New-ParameterNameResult '--list' 'List all available targets.'
New-ParameterNameResult '--single-target' 'Run only the specified target.' -Aliases '-s'
New-ParameterNameResult '--parallel' 'Run parallel with the given number of tasks.' -Aliases '-p'
New-ParameterNameResult '--environment-variable' "Set an environment variable. Use 'key=val'." -Aliases '-e'
)
}

$fakeBuildTarget = {
param($wordToComplete, $prev, $commandAst, $cursorPosition)

switch ($prev) {
'target' {return Get-BuildTargets $wordToComplete $commandAst $cursorPosition}
}
@()
}

$fakeRunTarget = {
param($wordToComplete, $prev, $commandAst, $cursorPosition)

switch ($prev) {
'target' {return Get-RunTargets $wordToComplete $commandAst $cursorPosition}
}
@()
}

$commandCompletions = @{
fake = @(
New-CommandResult 'build' 'build'
New-CommandResult 'run' 'run'
New-ParameterNameResult '--help' 'Show help.' -Aliases '-h'
New-ParameterNameResult '--version' 'Show version.'
New-ParameterNameResult '--verbose' 'Is ignored if -s is used.
* -v: Log verbose but only for FAKE
* -vv: Log verbose for Paket as well' -Aliases '-v', '-vv'
New-ParameterNameResult '--silent' 'Be silent, use this option if you need to pipe your output into another tool or need some additional processing.' -Aliases '-s'
)
'fake_build' = $fakeBuild
'fake_run' = $fakeRun
'fake_build_target' = $fakeBuildTarget
'fake_run_target' = $fakeRunTarget
}


function Get-Completions {
param (
[Parameter(Mandatory, Position = 0)]
[string]$Name,
[Object[]]$ArgumentList
)
function flatten {
Param($input)
$input | ForEach-Object {
if ($_ -is [array]) {
$_ | flatten
}
else {
$_
}
}
}
$commandCompletion = $commandCompletions[$command]

if ($commandCompletion -is [scriptblock]) {
$commandCompletion = Invoke-Command -ScriptBlock $commandCompletion -ArgumentList $ArgumentList
}

foreach ($c in $commandCompletion|flatten) {
if ($c -is [CompletionResult]) {
$c
}
}
}

Register-ArgumentCompleter -Native -CommandName fake -ScriptBlock {
param($wordToComplete, $commandAst, $cursorPosition)

$command = 'fake'
$prev = $null
for ($index = 1; $index -lt $commandAst.CommandElements.Count; $index++) {
$ce = $commandAst.CommandElements[$index]
if ($cursorPosition -lt $ce.Extent.EndColumnNumber) {
break
}

$text = $ce.Extent.Text
$prev = $text
$nextCommand = $command + "_$text"
if (!$text.StartsWith('-') -and $commandCompletions.ContainsKey($nextCommand)) {
$command = $nextCommand
}
}

$completions = Get-Completions $command -ArgumentList $wordToComplete, $prev, $commandAst, $cursorPosition
$completions | Where-Object {($_.CompletionText -Like "$wordToComplete*") } |
Sort-Object -Property ListItemText
}

Export-ModuleMember -Function @()
61 changes: 61 additions & 0 deletions help/markdown/fake-completion.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Command-line completion

Fake provides command-line completion for bash and PowerShell.

## Available completions

For PowerShell, the following completions are supported:

* available FAKE commands
* options supported by those commands
* available targets in a fake-script

For bash, only the available targets are currently supported.

## Installation for bash

### Prerequisites

* Tab completion for bash:

If you have tab completion for other commands (such as git parameters) then you can skip to [Install](#Install-completion-for-bash).
On OSX, you might have to do the following:

<pre><code class="lang-bash">
brew install bash-completion
</code></pre>
Paste the following into `~/.bash_profile` (create the file if it doesn't already exist)
<pre><code class="lang-bash">
if [ -f $(brew --prefix)/etc/bash_completion ]; then
. $(brew --prefix)/etc/bash_completion
fi
</code></pre>

### Install completion for bash
Download the contents of https:/fsharp/FAKE/tree/master/completion/bash and run

<pre><code class="lang-bash">
cd completion/bash
./install.sh
</code></pre>

## Installation for PowerShell

### Prerequisites

* PowerShell >= 5.0
* FAKE installed as a global tool

### Install completion for PowerShell

Download the `posh-fake` module from <https:/fsharp/FAKE/tree/master/completion/powershell/posh-fake.psm1>. Copy the module into a folder called `posh-fake`, inside one of your PowerShell module folders. You can find those in `$env:PSModulePath`.
For example C:\Users\UserName\Documents\WindowsPowerShell\Modules\posh-fake.

To import the module, run
<pre><code class="lang-bash">
Import-Module posh-fake
</code></pre>

If you do not want to manually import the module everytime you start PowerShell, you can add it to your PowerShell profile.
You can find your profile in `$PROFILE`.
Open the profile script (create the file if it doesn't already exist) and add the command `Import-Module posh-fake`.
3 changes: 2 additions & 1 deletion help/templates/template.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
<a href="/fake-commandline.html" class="navbar-item">Running FAKE from command line</a>
<a href="/fake-template.html" class="navbar-item">FAKE template</a>
<a href="/fake-debugging.html" class="navbar-item">Debugging scripts</a>
<a href="/fake-completion.html" class="navbar-item">FAKE command-line completion</a>
</div>
</div>

Expand Down Expand Up @@ -363,4 +364,4 @@
<script src="/assets/js/bulma.js"></script>
</body>

</html>
</html>

0 comments on commit bd74f3b

Please sign in to comment.