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