bash 탭 완성 명령을 작성 중이고 기본 작업이 작동합니다.
조금 더 복잡하게 만들려고 노력했지만 bash 매뉴얼이 별로 좋지 않습니다.
특히 매뉴얼에는 쉘 변수가 언급되어 있습니다 COMP_TYPE
.
각 유형을 트리거하는 요소와 해당 유형이 완료된 명령의 출력이 해석되는 방식을 변경하는지 여부를 파악하려고 합니다.
예를 들어 메뉴라는 "%" 유형이 있습니다.
제가 완료하는 명령에는 스위치 세트가 필요하므로 메뉴 유형이 실제로 어떤 종류의 메뉴를 표시하는지 궁금합니다.
> dcli compile -o -w hello.dart
명령 스위치에 대한 CLI 완성이 일부 서식과 함께 작은 메뉴에 표시되면 좋을 것입니다.
유형을 트리거하는 방법과 출력을 처리하는 방법에 대한 자세한 내용이 유용할 것입니다.
편집하다:
나는 세 가지 사항에 대해 명확성을 찾고 있습니다.
- 특정 유형을 선택하는 방법. 사용자가 실제로 %를 입력하여 메뉴 유형을 실행합니까?
입력해도 ls %
완료가 트리거되지 않는 것 같습니다.
사용자가 메뉴 유형을 트리거하는 경우 수행해야 할 작업을 수행한다는 것은 실제로 무엇을 의미합니까? 즉, 탭 완성을 위해 옵션 목록을 제공합니다. 메뉴 유형인 경우 무엇이 달라야 합니까?
사용자가 메뉴 유형을 트리거하면 bash가 완성 명령 출력을 처리하는 방식이 변경됩니다. 일반적인 탭 완성을 사용하면 완성 명령은 한 줄에 하나의 결과를 인쇄하고 bash는 이러한 결과를 옵션으로 표시합니다. 그렇다면 사용자가 선택한 메뉴 유형이 완성 명령이 출력할 수 있는 내용을 변경합니까, 아니면 bash가 출력을 해석/사용하는 방법을 변경합니까?
편집 2:
요청에 따라 완성된 Dart 코드는 다음과 같습니다.
void main(List<String> args) {
if (args.length < 2) {
printerr('dcli_complete provides tab completion from the bash command line for dcli');
printerr("You don't run dcli_complete directly");
exit(-1);
}
//var appname = args[0];
var word = args[1];
var commands = Commands.applicationCommands;
var results = <String>[];
var priorCommandFound = false;
// do we have a prior word.
if (args.length == 3) {
var priorWord = args[2];
//print('prior word: $priorWord');
if (priorWord.isNotEmpty) {
var priorCommand = Commands.findCommand(priorWord, Commands.asMap(Commands.applicationCommands));
if (priorCommand != null) {
/// We found a command let it complete the expansion according to its own rules
//print('priorCommand ${priorCommand.name}');
results = priorCommand.completion(word);
priorCommandFound = true;
}
}
}
if (!priorCommandFound) {
// find all commands that matches the 'word' using it as prefix
// and add them to the output.
for (var command in commands) {
if (command.name.startsWith(word)) {
results.add(command.name);
}
}
}
for (var result in results) {
print(result);
}
complete
"이전" 명령을 찾는 방법의 예입니다.
@override
List<String> completion(String word) {
return completionExpandScripts(word);
}
List<String> completionExpandScripts(String word, {String workingDirectory = '.'}) {
var root = workingDirectory;
/// expand ~ to the home dir.
if (word.startsWith('~')) {
word = word.replaceAll('~', HOME);
}
var searchTerm = word;
// a trailing slash and we treat the word as a directory.
if (word.endsWith(Platform.pathSeparator)) {
root = join(root, word);
searchTerm = '';
} else {
// no trailing slash but the word may contain a directory path
// in which case we use the last part as the search term
// and append any remaining path to the root.
if (word.isNotEmpty) {
var parts = split(word);
searchTerm = parts.last;
if (parts.length > 1) {
root = join(root, parts.sublist(0, parts.length - 1).join(Platform.pathSeparator));
}
}
}
/// if the resulting path is invalid return an empty list.
if (!exists(root)) return <String>[];
// /// if the work ends in a slash then we treat it as a directory
// /// then we need to use the directory as the root so we
// /// search in it.
// if (exists(join(root, searchTerm))) {
// root = join(root, searchTerm);
// searchTerm = '';
// }
var entries = find('$searchTerm*', types: [Find.directory, Find.file], root: root, recursive: false).toList();
var results = <String>[];
for (var script in entries) {
if (word.isEmpty || relative(script, from: workingDirectory).startsWith(word)) {
var matchPath = join(root, script);
String filePath;
if (isDirectory(matchPath)) {
// its a directory add trailing slash and returning.
filePath = '${relative('$script', from: workingDirectory)}/';
} else {
filePath = relative(script, from: workingDirectory);
}
if (filePath.contains(' ')) {
/// we quote filenames that include a space
filePath = '"$filePath"';
}
results.add(filePath);
}
}
return results;
}
편집 3:
이것은 내가 지금까지 찾은 것 중 가장 자세한 설명이지만 여전히 별 도움이 되지 않습니다.
매뉴얼에 따르면:
COMP_TYPE은 완성 함수를 호출하게 만든 시도된 완성 유형에 해당하는 정수 값으로 설정됩니다. TAB, 일반 완성의 경우, ?, 연속된 탭 뒤의 완성 목록 표시, !, 부분 단어 완성 항목에 대한 대체 목록 표시, @ 목록 완성(단어가 수정되지 않은 경우) 또는 %(메뉴 완성). 이 변수는 프로그래밍 가능 완성 도구에 의해 호출되는 셸 함수 및 외부 명령에서만 사용할 수 있습니다(아래 프로그래밍 가능 완성 참조).
TAB을 얻을 수 있나요? 그리고 % 하지만 어떻게 얻는지 모르겠어요! 그리고@.
!' when a user hits TAB with
"show-all-if-ambiguously" 세트(가능한 완성이 즉시 나열되도록 함)와 @' if the user hits TAB with
"show-all-if-unmodified" 세트(가능한 완성에는 공통 접두사가 없으므로 표시될 수 없음)가 표시되어야 합니다. 부분 완료이므로 완료가 즉시 표시됩니다. readline에서 요구하는 완성 유형에 대한 내부 값이며 COMP_TYPE 값에 반영됩니다.
이 스택 오버플로 기사는 show-if-xxx 설정이 수행하는 작업에 대한 몇 가지 설명을 제공하지만 readline이 실행되는 방식에 영향을 미치는 것으로 보이지만 readline이 완료 명령과 어떻게 상호 작용하는지 명확하지 않습니다.
https://stackoverflow.com/questions/42192384/show-all-if-ambigously-vs-show-all-if-unmodified
또한 '%' COMP_TYPE과 그것이 어떻게 트리거되는지 설명하지 않습니다.