Last active
April 10, 2017 20:15
-
-
Save powercode/318b7f844d81815551227f62aa41042a to your computer and use it in GitHub Desktop.
Generation of ArgumentCompleter for ripgrep
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
. C:\Users\Staffan\Documents\WindowsPowerShell\JoinItem.ps1 | |
class OptionHelp { | |
[string] $Short | |
[string] $Long | |
[string] $Arg | |
[string] $Help | |
} | |
function Get-RGOption { | |
[CmdletBinding()] | |
param() | |
switch -regex ((D:\repos\ripgrep\target\release\rg.exe --help)) { | |
'^\s{4}(?<short>-\w), (?<long>--\S+)(?:\s(?<arg>\<\w+\>))?' { | |
$o = [OptionHelp] @{ | |
Short = $matches.short | |
Long = $matches.Long | |
Arg = $matches.Arg | |
} | |
[string[]] $help = @() | |
while ($switch.MoveNext()) { | |
if ([string]::IsNullOrWhiteSpace($switch.Current)) { | |
break | |
} | |
$Help += $switch.Current.Trim() | |
} | |
$o.Help = $help -join [Environment]::NewLine | |
$o | |
} | |
'^\s{8}(?<long>--\S+)(?:\s(?<arg>\<\w+\>))?' { | |
$o = [OptionHelp] @{ | |
Long = $matches.Long | |
Arg = $matches.Arg | |
} | |
[string[]] $help = @() | |
while ($switch.MoveNext()) { | |
if ([string]::IsNullOrWhiteSpace($switch.Current)) { | |
break | |
} | |
$help += $switch.Current.Trim() | |
} | |
$o.Help = $help -join [Environment]::NewLine | |
$o | |
} | |
} | |
} | |
function New-RGCompleter { | |
$opt = Get-RGOption | |
$adds = $opt.foreach{ | |
$short = $_.Short | |
$long = $_.Long | |
$help = $_.Help.Replace("'", "''") | |
if ($help.Contains("`n")) { | |
$help = @" | |
@`" | |
$help | |
`"@ | |
"@ | |
} | |
else { | |
$help = "'$help'" | |
} | |
if ($short) { | |
$list = ($short + ' ' + $_.Arg).TrimEnd() | |
@" | |
`t`tif ([RGCompleter]::ShouldAdd("$short", `$wordToComplete, `$prevOpts, `$multiOpts)) { | |
`t`t`t`$result.Add([CompletionResult]::new("$short", "$list", [CompletionResultType]::ParameterName, $help)) | |
`t`t} | |
`t | |
"@ | |
} | |
else { | |
$list = ($long + ' ' + $_.Arg).TrimEnd() | |
@" | |
`t`tif ([RGCompleter]::ShouldAdd("$long", `$wordToComplete, `$prevOpts, `$multiOpts)) { | |
`t`t`t`$result.Add([CompletionResult]::new("$long", "$list", [CompletionResultType]::ParameterName, $help)) | |
`t`t} | |
"@ | |
} | |
} | |
$hasArgs = $opt.Where{$_.Arg}.Foreach{if ($_.short) {$_.short}; $_.long} | Join-Item -Quote | |
$multi = $opt.Where{$_.Help -match 'multiple'}.Foreach{if ($_.short) {$_.short}; $_.long} | Join-Item -Quote | |
$ofs = [Environment]::NewLine | |
@" | |
using namespace System.Collections.Generic | |
using namespace System.Management.Automation | |
class RGCompleter { | |
static [bool] ShouldAdd([string] `$completionText, [string] `$wordToComplete, [string[]] `$previousCommand, [string[]] `$multiOpt) { | |
if (`$completionText.StartsWith(`$wordToComplete, [StringComparison]::OrdinalIgnoreCase)){ | |
if (`$completionText -in `$previousCommand -and `$completionText -notin `$multiOpt) { | |
return `$false | |
} | |
return `$true | |
} | |
return `$false | |
} | |
static [string[]] GetPreviousOptions([Language.CommandAst] `$ast, [int] `$cursorColumn) { | |
if (`$ast.CommandElements.Count -eq 1) { | |
return [string[]]::new(0) | |
} | |
return `$ast.CommandElements.Foreach{`$_.Extent.Text} | |
} | |
static [List[CompletionResult]] CompleteArgument([string] `$command, [string] `$previousCommand, [string]`$wordToComplete) { | |
`$result = [List[CompletionResult]]::new(10) | |
switch -regex -CaseSensitive (`$previousCommand){ | |
'-(A|B|C)' { | |
(1..10).Where{"`$_".StartsWith(`$wordToComplete)}.Foreach{ | |
`$result.Add([CompletionResult]::new(`$_,`$_, [CompletionResultType]::ParameterValue, `$_)) | |
} | |
} | |
'--color(?!s)' { | |
('never','auto','always','ansi').Where{"`$_".StartsWith(`$wordToComplete)}.Foreach{ | |
`$result.Add([CompletionResult]::new(`$_,`$_, [CompletionResultType]::ParameterValue, `$_)) | |
} | |
} | |
'--colors' { | |
`$type = 'path','line','match' | |
`$attrib = 'fg','bg','style','none' | |
`$style ='nobold','bold','nointense','intense' | |
`$color = 'red','blue','green','cyan','magenta','yellow','white','black' | |
`$t,`$a,`$v = `$wordToComplete.Trim().Split(':') | |
`$completions = `$type.Foreach{ | |
`$t=`$_ | |
"`${t}:none" | |
('fg','bg').Foreach{`$a = `$_; `$color.Foreach{"`${t}:`${a}:`$_"}} | |
`$style.Foreach{"`${t}:style:`$_"} | |
}.Where{ | |
`$_.StartsWith(`$wordToComplete, [Stringcomparison]::OrdinalIgnoreCase) | |
}.Foreach{`$result.Add([CompletionResult]::new(`$_, `$_, [CompletionResultType]::ParameterValue, `$_))} | |
} | |
'-(T|t)' { | |
(& `$command --type-list).Foreach{ | |
`$c, `$t = `$_.Split(":",2) | |
if (`$c.StartsWith(`$wordToComplete, [StringComparison]::OrdinalIgnoreCase)) { | |
`$r = [CompletionResult]::new(`$c,`$c, [CompletionResultType]::ParameterValue, `$t) | |
`$result.Add(`$r) | |
} | |
} | |
} | |
} | |
return `$result; | |
} | |
static [List[CompletionResult]] CompleteInput([string] `$wordToComplete, [Language.CommandAst] `$ast, [int] `$cursorColumn){ | |
`$hasArgOpts = $hasArgs | |
`$multiOpts = $multi | |
`$prevOpts = [RGCompleter]::GetPreviousOptions(`$ast, `$cursorColumn) | |
`$command = `$ast.CommandElements[0].Extent.Text | |
if (`$prevOpts.Length -gt 1 -and `$wordToComplete) { | |
`$previous = `$prevOpts[-2] | |
} | |
else { | |
`$previous = `$prevOpts[-1] | |
} | |
if (`$previous -in `$hasArgOpts) { | |
return [RGCompleter]::CompleteArgument(`$command, `$previous, `$wordToComplete) | |
} | |
`$result = [List[CompletionResult]]::new(60) | |
$adds | |
return `$result | |
} | |
} | |
Register-ArgumentCompleter -native -CommandName 'rg.exe' -scriptblock { | |
param([string] `$wordToComplete, [Language.CommandAst] `$ast, [int] `$cursorPosition) | |
return [RGCompleter]::CompleteInput(`$wordToComplete, `$ast, `$cursorPosition) | |
} | |
function Test-Completion{ | |
param([string] `$cmd, | |
[string] `$wordToComplete, | |
[int]`$cursorColumn | |
) | |
if (`$cursorColumn -eq 0){ | |
`$cursorColumn = `$cmd.Length | |
} | |
`$tokens = `$null | |
`$errors =`$null | |
`$ast = [Language.Parser]::ParseInput(`$cmd, [ref]`$tokens, [ref]`$errors) | |
`$commandAst = `$ast.EndBlock.Statements.PipelineElements[0] | |
[RGCompleter]::CompleteInput(`$wordToComplete, `$commandAst, `$cursorColumn) | |
} | |
"@ | |
} | |
New-RGCompleter | Set-Content C:\Users\Staffan\Documents\WindowsPowerShell\rgcompleter.ps1 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment