Skip to content

Instantly share code, notes, and snippets.

@Bak-Jin-Hyeong
Last active July 10, 2017 09:02
Show Gist options
  • Save Bak-Jin-Hyeong/056a397763fcf584d9ca346e099313a9 to your computer and use it in GitHub Desktop.
Save Bak-Jin-Hyeong/056a397763fcf584d9ca346e099313a9 to your computer and use it in GitHub Desktop.
ripgrep (https://github.com/BurntSushi/ripgrep) tab completion in powershell
function Get-AliasPattern($exe) {
$aliases = @($exe) + @(Get-Alias | Where-Object { $_.Definition -eq $exe } | Select-Object -Exp Name)
"($($aliases -join '|'))"
}
$options = @(
@(@('-A', '--after-context'), @('<NUM>')),
@(@('-B', '--before-context'), @('<NUM>')),
@(@('-S', '--case-sensitive'), @()),
@(@('', '--color'), @('never', 'auto', 'always', 'ansi')),
@(@('', '--colors'), @('{type}:{attribute}:{value}')),
@(@('', '--column'), @()),
@(@('-C', '--context'), @('<NUM>')),
@(@('', '--context-separator'), @('<SEPARATOR>')),
@(@('-c', '--count'), @()),
@(@('', '--debug'), @()),
@(@('', '--dfa-size-limit'), @('<NUM+SUFFIX?>')),
@(@('-E', '--encoding'), @(
'auto',
'unicode-1-1-utf-8',
'utf-8',
'866',
'cp866',
'csibm866',
'ibm866',
'csisolatin2',
'iso-8859-2',
'iso-ir-101',
'iso8859-2',
'iso88592',
'iso_8859-2',
'iso_8859-2:1987',
'l2',
'latin2',
'csisolatin3',
'iso-8859-3',
'iso-ir-109',
'iso8859-3',
'iso88593',
'iso_8859-3',
'iso_8859-3:1988',
'l3',
'latin3',
'csisolatin4',
'iso-8859-4',
'iso-ir-110',
'iso8859-4',
'iso88594',
'iso_8859-4',
'iso_8859-4:1988',
'l4',
'latin4',
'csisolatincyrillic',
'cyrillic',
'iso-8859-5',
'iso-ir-144',
'iso8859-5',
'iso88595',
'iso_8859-5',
'iso_8859-5:1988',
'arabic',
'asmo-708',
'csiso88596e',
'csiso88596i',
'csisolatinarabic',
'ecma-114',
'iso-8859-6',
'iso-8859-6-e',
'iso-8859-6-i',
'iso-ir-127',
'iso8859-6',
'iso88596',
'iso_8859-6',
'iso_8859-6:1987',
'csisolatingreek',
'ecma-118',
'elot_928',
'greek',
'greek8',
'iso-8859-7',
'iso-ir-126',
'iso8859-7',
'iso88597',
'iso_8859-7',
'iso_8859-7:1987',
'sun_eu_greek',
'csiso88598e',
'csisolatinhebrew',
'hebrew',
'iso-8859-8',
'iso-8859-8-e',
'iso-ir-138',
'iso8859-8',
'iso88598',
'iso_8859-8',
'iso_8859-8:1988',
'visual',
'csiso88598i',
'iso-8859-8-i',
'logical',
'csisolatin6',
'iso-8859-10',
'iso-ir-157',
'iso8859-10',
'iso885910',
'l6',
'latin6',
'iso-8859-13',
'iso8859-13',
'iso885913',
'iso-8859-14',
'iso8859-14',
'iso885914',
'csisolatin9',
'iso-8859-15',
'iso8859-15',
'iso885915',
'iso_8859-15',
'l9',
'iso-8859-16',
'cskoi8r',
'koi',
'koi8',
'koi8-r',
'koi8_r',
'koi8-ru',
'koi8-u',
'csmacintosh',
'mac',
'macintosh',
'x-mac-roman',
'dos-874',
'iso-8859-11',
'iso8859-11',
'iso885911',
'tis-620',
'windows-874',
'cp1250',
'windows-1250',
'x-cp1250',
'cp1251',
'windows-1251',
'x-cp1251',
'ansi_x3.4-1968',
'ascii',
'cp1252',
'cp819',
'csisolatin1',
'ibm819',
'iso-8859-1',
'iso-ir-100',
'iso8859-1',
'iso88591',
'iso_8859-1',
'iso_8859-1:1987',
'l1',
'latin1',
'us-ascii',
'windows-1252',
'x-cp1252',
'cp1253',
'windows-1253',
'x-cp1253',
'cp1254',
'csisolatin5',
'iso-8859-9',
'iso-ir-148',
'iso8859-9',
'iso88599',
'iso_8859-9',
'iso_8859-9:1989',
'l5',
'latin5',
'windows-1254',
'x-cp1254',
'cp1255',
'windows-1255',
'x-cp1255',
'cp1256',
'windows-1256',
'x-cp1256',
'cp1257',
'windows-1257',
'x-cp1257',
'cp1258',
'windows-1258',
'x-cp1258',
'x-mac-cyrillic',
'x-mac-ukrainian',
'chinese',
'csgb2312',
'csiso58gb231280',
'gb2312',
'gb_2312',
'gb_2312-80',
'gbk',
'iso-ir-58',
'x-gbk',
'gb18030',
'big5',
'big5-hkscs',
'cn-big5',
'csbig5',
'x-x-big5',
'cseucpkdfmtjapanese',
'euc-jp',
'x-euc-jp',
'csiso2022jp',
'iso-2022-jp',
'csshiftjis',
'ms932',
'ms_kanji',
'shift-jis',
'shift_jis',
'sjis',
'windows-31j',
'x-sjis',
'cseuckr',
'csksc56011987',
'euc-kr',
'iso-ir-149',
'korean',
'ks_c_5601-1987',
'ks_c_5601-1989',
'ksc5601',
'ksc_5601',
'windows-949',
'csiso2022kr',
'hz-gb-2312',
'iso-2022-cn',
'iso-2022-cn-ext',
'iso-2022-kr',
'utf-16be',
'utf-16',
'utf-16le',
'x-user-defined'
)),
@(@('-f', '--file'), @('<FILE>')),
@(@('', '--files'), @()),
@(@('-l', '--files-with-matches'), @()),
@(@('-l', '--files-without-match'), @()),
@(@('-F', '--fixed-strings'), @()),
@(@('-L', '--follow'), @()),
@(@('-g', '--glob'), @('<GLOB>')),
@(@('-h', '--help'), @()),
@(@('', '--heading'), @()),
@(@('', '--hidden'), @()),
@(@('-i', '--ignore-case'), @()),
@(@('', '--ignore-file'), @('<FILE>')),
@(@('-v', '--invert-match'), @()),
@(@('-n', '--line-number'), @()),
@(@('-M', '--max-columns'), @('<NUM>')),
@(@('-m', '--max-count'), @('<NUM>')),
@(@('-m', '--max-count'), @('<NUM>')),
@(@('', '--max-filesize'), @('<NUM+SUFFIX?>')),
@(@('', '--maxdepth'), @('<NUM>')),
@(@('', '--mmap'), @()),
@(@('', '--no-filename'), @()),
@(@('', '--no-heading'), @()),
@(@('', '--no-ignore'), @()),
@(@('', '--no-ignore-parent'), @()),
@(@('', '--no-ignore-vcs'), @()),
@(@('-N', '--no-line-number'), @()),
@(@('', '--no-messages'), @()),
@(@('', '--no-mmap'), @()),
@(@('-0', '--null'), @()),
@(@('-o', '--only-matching'), @()),
@(@('', '--path-separator'), @('"/"', '"\"')),
@(@('-p', '--pretty'), @()),
@(@('-q', '--quiet'), @()),
@(@('', '--regex-size-limit'), @('<NUM+SUFFIX?>')),
@(@('-e', '--regexp'), @('<PATTERN>')),
@(@('-r', '--replace'), @('<ARG>')),
@(@('-S', '--smart-case'), @()),
@(@('', '--sort-files'), @()),
@(@('-a', '--text'), @()),
@(@('-j', '--threads'), @('<NUM>')),
@(@('-t', '--type'), @('<TYPE>')),
@(@('', '--type-add'), @('"src:include:cpp,py,md"', '"foo:*.foo"')),
@(@('', '--type-clear'), @('<TYPE>')),
@(@('', '--type-list'), @()),
@(@('-T', '--type-not'), @('<TYPE>')),
@(@('-u', '--unrestricted'), @()),
@(@('-V', '--version'), @()),
@(@('', '--vimgrep'), @()),
@(@('-H', '--with-filename'), @()),
@(@('-w', '--word-regexp'), @())
)
$colors_value = @('red', 'blue', 'green', 'cyan', 'magenta', 'yellow', 'white', 'black')
$colors_style = @('nobold', 'bold', 'nointense', 'intense')
$colors_attribute = @('fg', 'bg', 'none', 'style')
$colors_type = @('path', 'line', 'column', 'match')
function parse_option($parameters) {
if (!($parameters -match '(^|\s+)(?<lastOption>\-\S+)\s+(?<lastToken>\S*)$')) {
return @(@(), @(), '')
}
$lastOption = $Matches['lastOption']
$options | Where-Object {
$_[0] -ccontains $lastOption
} | Select-Object -First 1 | ForEach-Object {
$option = $_[0]
$completionList = $_[1]
$wordToComplete = $Matches['lastToken']
return @($option, $completionList, $wordToComplete)
}
}
function RipgrepTabExpansion($lastBlock) {
$parameters = ($lastBlock -replace "^$(Get-AliasPattern rg)(\.exe)?\s+","")
$parsed = (parse_option $parameters)
$option = $parsed[0]
$completionList = $parsed[1]
$wordToComplete = $parsed[2]
if ($option -and $completionList) {
if ($completionList[0] -eq '<ARG>') {
$completionList = $completionList + @('""')
}
elseif ($completionList[0] -eq '<FILE>') {
$completionList = @()
}
elseif ($completionList[0] -eq '<GLOB>') {
$completionList = $completionList + @('""')
}
elseif ($completionList[0] -eq '<NUM+SUFFIX?>') {
$completionList = $completionList + @(0 .. 9)
}
elseif ($completionList[0] -eq '<NUM>') {
$completionList = $completionList + @(0 .. 9)
}
elseif ($completionList[0] -eq '<PATTERN>') {
$completionList = $completionList + @('""')
}
elseif ($completionList[0] -eq '<SEPARATOR>') {
$completionList = $completionList + @('""', '"--"', '"\t"', '"\x7F"')
}
elseif ($completionList[0] -eq '<TYPE>') {
$completionList = $completionList + (
rg --type-list | ForEach-Object {
$_.SubString(0, $_.IndexOf(':'))
}
)
}
elseif ($option -eq '--colors') {
$tokens = $wordToComplete -split ':'
if ($tokens.Count -eq 1) {
$completionList = $completionList + $colors_type
}
elseif ($tokens.Count -eq 2) {
$completionList = $completionList + (
$colors_attribute | ForEach-Object {
$tokens[0] + ':' + $_
}
)
}
elseif ($tokens.Count -eq 3 -and $tokens[1] -eq 'style') {
$completionList = $completionList + (
$colors_style | ForEach-Object {
$tokens[0] + ':' + $tokens[1] + ':' + $_
}
)
}
else {
$completionList = $completionList + (
$colors_value | ForEach-Object {
$tokens[0] + ':' + $tokens[1] + ':' + $_
}
)
}
}
$completionList | Where-Object { $_ -like "${wordToComplete}*" }
}
elseif ($parameters -match '(^|\s+)(?<lastToken>\S*)$') {
$completionList = $options | ForEach-Object { $_[0] } | Where-Object { $_ }
$wordToComplete = $Matches['lastToken']
$completionList | Where-Object { $_ -like "${wordToComplete}*" }
}
}
$PowerTab_RegisterTabExpansion = if (Get-Module -Name powertab) { Get-Command Register-TabExpansion -Module powertab -ErrorAction SilentlyContinue }
if ($PowerTab_RegisterTabExpansion)
{
& $PowerTab_RegisterTabExpansion "rg" -Type Command {
param($Context, [ref]$TabExpansionHasOutput, [ref]$QuoteSpaces) # 1:
$line = $Context.Line
$lastBlock = [regex]::Split($line, '[|;]')[-1].TrimStart()
$TabExpansionHasOutput.Value = $true
RipgrepTabExpansion $lastBlock
}
return
}
if (Test-Path Function:\TabExpansion) {
Rename-Item Function:\TabExpansion TabExpansionBackup
}
function TabExpansion($line, $lastWord) {
$lastBlock = [regex]::Split($line, '[|;]')[-1].TrimStart()
switch -regex ($lastBlock) {
# Execute rg tab completion for all rg-related commands
"^$(Get-AliasPattern rg)(\.exe)? (.*)" {
RipgrepTabExpansion $lastBlock
}
# Fall back on existing tab expansion
default { if (Test-Path Function:\TabExpansionBackup) { TabExpansionBackup $line $lastWord } }
}
}
if (Get-Module RipgrepTabExpansion) { return }
$thisDirectory = (Split-Path -parent $MyInvocation.MyCommand.Definition)
. $thisDirectory\RipgrepTabExpansion.ps1
Export-ModuleMember -Function 'TabExpansion'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment