PowerShell 명령어
파일 경로를 CLI(Command Line Interface)에 입력할 때 Tab으로 후보 목록이 나타나지만, 자주 사용하는 zenn-cli 명령어도 자동 완성되었으면 합니다.
Ubuntu에서는 자동으로 되어 있는 기능을 Windows에서도 설정하면 사용할 수 있게 되었고, 제가 직접 시도해 본 결과를 보고합니다.
꽤 편리하지만 의외로 할 수 있다는 것을 아는 사람이 적은 것 같습니다.
환경 준비
다음 기사를 참고하여 설치 작업을 진행하겠습니다.
PowerShell 7을 사용하기 위해 현재 환경에 설치된 PowerShell 버전을 확인합니다.
제 PC에는 기본적으로 PowerShell 5가 설치되어 있었습니다.
$PSVersionTable.PSVersion
Major Minor Build Revision
----- ----- ----- --------
5 1 26100 9711
PowerShell 7을 설치합니다.
winget install --id Microsoft.PowerShell --source winget
Starting package install...
██████████████████████████████ 100%
Successfully installed
PowerShell 7을 기본 터미널로 설정합니다.
Windows Terminal에서 ctrl+,를 눌러 설정을 열고, 기본 프로필(default profile)을 PowerShell로 전환합니다.
제 환경의 경우, 여기도 기본값이 Windows PowerShell 5였습니다.
저의 환경에서는 VSCode의 기본 프로필도 동시에 전환되었습니다.
이후부터는 pwsh로 실행합니다.
Install-PSResource CompletionPredictor -Scope CurrentUser
Install-PSResource PSFzf -Scope CurrentUser # 히스토리 모호 검색을 원한다면
winget install junegunn.fzf # PSFzf를 사용할 경우 본체도
이 시점에서 pwsh를 열면, 히스토리가 나타나게 되었습니다.
이것만으로도 상당히 편리합니다.
자동 완성 함수 파일 생성하기
자동 완성 함수는 Tab 키를 눌렀을 때 PowerShell에게 다음에 입력할 수 있는 명령어 후보를 알려주는 작은 프로그램입니다.
Get-ChildItem 같은 PowerShell 자체 명령어는 처음부터 후보가 나오지만, npx zenn 같은 명령어는 그 내부 내용을 알지 못합니다.
따라서 Tab을 눌러도 일단 디렉터리상의 파일 이름만 출력됩니다.
자동 완성 함수는 명령어 사용법에 대한 지식을 보완해 줍니다.
자동 완성 함수는 .ps1로 저장하는 파일이며, PowerShell 7의 $PROFILE과 같은 폴더에 저장합니다.
제 경우에는 문서/PowerShell/ 바로 아래였습니다.
zenn-cli 명령어용 자동 완성 함수를 만듭니다.
자동 완성 함수
$zennSpec = @{
'' = @('init', 'preview', 'new:article', 'new:book', 'list:articles', 'list:books', 'scrap', 'image', '--version', '--help')
'preview' = @('--port', '--no-watch', '--open', '--host', '--help')
...
pwsh에서 다음 명령어를 실행하여 tech와 idea가 나오면 성공입니다.
. (Join-Path (Split-Path $PROFILE) 'zenn-completer.ps1');
$s = 'npx zenn new:article --type ';
(TabExpansion2 -inputScript $s -cursorColumn $s.Length).CompletionMatches.CompletionText
다음으로 $PROFILE을 생성하기 위해, $PROFILE을 메모장으로 엽니다.
파일에 다음 내용을 작성합니다.
새로운 pwsh를 열면 명령어가 자동 완성됩니다.
History에서 오는 보완도 나오고,
alt text
등록한 보완 함수의 보완 결과도 제대로 나옵니다.
alt text
이번에는 zenn-cli의 명령어를 보완 함수에 추가했지만, 다른 툴에 대해서도 보완 함수를 추가함으로써 자동 완성은 가능합니다.
보완 함수의 만들기
툴로 보완 함수를 만드는 패턴
gh나 uv 같은 것은 보완 함수의 .ps1을 출력해 줍니다.
시험 삼아 uv로 만들어 보겠습니다.
이 ps1 파일을 아까와 같은 디렉토리에 저장합니다.
uv generate-shell-completion powershell | Out-File (Join-Path (Split-Path $PROFILE) 'uv-completer.ps1')
또한, $PROFILE에 다음 로드 처리를 추가합니다.
. (Join-Path (Split-Path $PROFILE) 'uv-completer.ps1')
직접 만드는 패턴
{툴} --help로 completion 같은 인수가 있는지 확인하고, 없다면 자작해야 합니다.
zenn-cli의 --help에는 없었기 때문에 자작할 필요가 있었습니다.
먼저, 최소한의 보완 함수 형태부터 살펴보겠습니다.
Register-ArgumentCompleter -Native -CommandName mytool -ScriptBlock {
param($wordToComplete, $commandAst, $cursorPosition)
'build', 'test', 'clean' | Where-Object { $_ -like "$wordToComplete*" }
...
-Native:
exe나 npx처럼 PowerShell 외부에서 실행되는 명령어라는 의미입니다. -
-CommandName:
명령어 이름입니다. npx, npx.cmd처럼 여러 개 나열할 수 있습니다. -
-ScriptBlock의 {}:
이 안에 내용물이 보완 함수입니다. Tab을 누를 때마다 호출되며, 출력하는 문자열이 후보로 표시됩니다. -
Where-Object:
입력된 문자열로 후보를 좁힙니다. 작성하지 않으면 mytool te까지 치고 Tab을 눌러도, build 같은 관계없는 명령어까지 후보에 나옵니다.
자동 완성이 이루어졌을 때, 이 보완 함수에 전달되는 인수는 다음과 같습니다.
가령, npx zenn new:article --ty에서 Tab을 누른 경우를 가정합니다.
| 인수 | 내용물 | 값 |
|---|
| $wordToComplete | 입력 중인 단어. 공백 직후라면 비어 있음 | --ty |
| $commandAst | 행 전체를 분석한 것. .CommandElements로 단어 배열을 얻을 수 있습니다. 커서보다 뒤의 단어도 포함됩니다. | npx, zenn, new:article, --ty |
| $cursorPosition | 커서의 위치 | (예) 25 |
많은 툴의 명령어는 첫 번째 단어가 하위 명령어, 그 뒤에 옵션, 옵션에 의해 결정된 값이라는 전형적인 형태를 하고 있습니다.
설명에서는 이 전형적인 툴을 대상으로 한 경우의 틀을 보여줍니다.
# --- mytool의 보완 ---
$mytoolSpec = @{
'' = @('build', 'test', 'clean') # 첫 번째 단어(하위 명령어)
...
이 틀을 등록했을 경우, 다음과 같은 자동 완성 후보가 표시됩니다.
| 입력 | 자동 완성 후보 |
|---|
mytool | |
없음 | |
mytool␣ | build, test, clean |
mytool b␣ | build |
mytool build␣ | --release, --target |
mytool build --target␣ | x86, x64, arm64 |
자동 완성 후보 문자열을 그대로 표시하는 대신, 다음과 같은 CompletionResult를 반환하면 Tab 목록에서 선택하고 있는 후보에 대한 설명도 표시할 수 있습니다.
| 순서 | 의미 | 예 |
|---|
| 1 | 선택되었을 때 입력되는 문자열 | $_ |
| ... | 'ParameterValue' | |
| 4 | 설명 | $tip |
$mytoolValues = @{
'--target' = @('x86', 'x64', 'arm64') # 값이 결정된 옵션
}
...
만든 자동 완성 함수는 이전과 마찬가지로 도구명-completer.ps1라는 파일 이름으로 저장하고, $PROFILE에 로드 처리(読み込み処理)를 추가합니다.
혹은, *-completer.ps1을 자동으로 읽도록 다음처럼 대체할 수 있습니다.
- . (Join-Path (Split-Path $PROFILE) 'zenn-completer.ps1')
- . (Join-Path (Split-Path $PROFILE) 'uv-completer.ps1')
+ foreach ($f in Get-ChildItem (Split-Path $PROFILE) -Filter '*-completer.ps1') { . $f.FullName }
요약
이로써 PowerShell에서도 자동 완성을 구현할 수 있었습니다.
Windows에서는 안 될 거라고 생각해서 방치하고 있었는데, 할 수 있다면 정말 감사한 기능이라고 생각합니다.
일일이 도구마다 설정하는 번거로움은 있지만, 방법을 알게 되었으니 이제 Claude에게 부탁하면 조금만 하면 할 것 같습니다.
다음에는 지루하게 시작 옵션이 많은 Claude의 시작 명령어 자동 완성을 만들어 보고 싶습니다.
여러분도 한번 시도해 보세요.
다른 글
이것도 Windows 표준 기능으로는 안 된다고 포기했던, 고기능 탐색기에 관한 글입니다.
Discussion