PowerShell で Git をもっと便利に使う

2021/09/02に公開

posh-git

まだの人はとにかく dahlbyk/posh-git をインストールしましょう。

インストール方法は README.mdInstallation のところに書いてある通り。PowerShellGet を使う方法、Chocolatey を使う方法、手動で行う方法の三種類書いてありますが、手動でインストールしても全然難しくありません。ダウンロードして適当なディレクトリに展開し、$PROFILE で示されたファイルに Import-Module を書いて posh-git.psd1 をインポートするだけです。

これで Git コマンドのタブ補完がきくようになるだけでなく、リポジトリのあるディレクトリに移動すると自動的にステータスを表示します。無茶苦茶便利です。

タブ補完をもっと便利に

posh-git でも十分便利なのですが、いちいち gitと打つのも煩わしくなってきたので、さらに短く補完することにしました。リポジトリのあるディレクトリでは、add と打ってタブを押すだけで git add に展開したり、commitgit-commit -m に補完できます。前方一致で検索するので、さらに短く a でも git add が候補として出てきます。

これは posh-git と共存できますし、posh-git が無くても問題ありません。

次のコードを GitTabExpansion.psm1 という名前で保存し、先ほどのようにプロファイルで起動時に一度 Import-Module "~\Documents\Windows PowerShell\Modules\GitTabExpansion" などのように呼び出すようにしてください。

using namespace System.Management.Automation

<# Options include:
     RelativeFilePaths - [bool]
         Always resolve file paths using Resolve-Path -Relative.
         The default is to use some heuristics to guess if relative or absolute is better.

   To customize your own custom options, pass a hashtable to CompleteInput, e.g.
         return [System.Management.Automation.CommandCompletion]::CompleteInput($inputScript, $cursorColumn,
             @{ RelativeFilePaths=$false }
#>

function TabExpansion2 {
	[CmdletBinding(DefaultParameterSetName = 'ScriptInputSet')]
	Param(
		[Parameter(ParameterSetName = 'ScriptInputSet', Mandatory = $true, Position = 0)]
		[string] $inputScript,

		[Parameter(ParameterSetName = 'ScriptInputSet', Mandatory = $true, Position = 1)]
		[int] $cursorColumn,

		[Parameter(ParameterSetName = 'AstInputSet', Mandatory = $true, Position = 0)]
		[System.Management.Automation.Language.Ast] $ast,

		[Parameter(ParameterSetName = 'AstInputSet', Mandatory = $true, Position = 1)]
		[System.Management.Automation.Language.Token[]] $tokens,

		[Parameter(ParameterSetName = 'AstInputSet', Mandatory = $true, Position = 2)]
		[System.Management.Automation.Language.IScriptPosition] $positionOfCursor,

		[Parameter(ParameterSetName = 'ScriptInputSet', Position = 2)]
		[Parameter(ParameterSetName = 'AstInputSet', Position = 3)]
		[Hashtable] $options = $null
	)

	End
	{
		if ($psCmdlet.ParameterSetName -eq 'ScriptInputSet')
		{
			$result = [System.Management.Automation.CommandCompletion]::CompleteInput(
				<#inputScript#>  $inputScript,
				<#cursorColumn#> $cursorColumn,
				<#options#>      $options)
			if (Test-Path '.\.git') {
				$candidates = @{
					add = 'git add ';
					gac = 'git add -A; git commit -m ';
					commit = 'git commit -m ';
					push = 'git push';
					branch = 'git branch ';
					log = 'git log';
					status = 'git status';
					show = 'git show ';
					diff = 'git diff';
					checkout = 'git checkout ';
					pull = 'git pull';
					fetch = 'git fetch';
					merge = 'git merge ';
					rebase = 'git rebase '
				}
				$matches = $candidates.Keys | Where-Object {
					$_.StartsWith($inputScript)
				}
				if ($matches -ne $null) {
					$matches | Foreach-Object {
						$result.CompletionMatches.Insert(0, [CompletionResult]::new($candidates[$_]))
					}
				}
			}
			return $result;
		}
		else
		{
			return [System.Management.Automation.CommandCompletion]::CompleteInput(
				<#ast#>              $ast,
				<#tokens#>           $tokens,
				<#positionOfCursor#> $positionOfCursor,
				<#options#>          $options)
		}
	}
}

Export-ModuleMember -Function TabExpansion2

なお、リポジトリの無いディレクトリでは補完しない仕様です。また、コマンドを追加したい時には適当に $candidates をいじってください。

執筆日: 2019/02/21

GitHubで編集を提案

Discussion