$values) { if (str_ends_with($option, '=')) { continue; } $valueCases .= ' ' . self::bashPattern($option) . ")\n" . ' COMPREPLY=( $(compgen -W ' . self::quote(self::words($values)) . ' -- "$current") )' . "\n" . " return\n ;;\n"; } $quotedOptions = self::quote($options); $directoryOptions = implode('|', array_map(self::bashPattern(...), CompletionMetadata::directoryOptions())); $pythonFileOptions = implode('|', array_map(self::bashPattern(...), CompletionMetadata::pythonFileOptions())); $outputFileOptions = implode('|', array_map(self::bashPattern(...), CompletionMetadata::outputFileOptions())); $equalsCases = ''; foreach (CompletionMetadata::values() as $option => $values) { if (!str_ends_with($option, '=')) { continue; } $prefix = substr($option, 0, -1); $equalsCases .= ' ' . self::bashPattern($prefix) . "=*)\n" . ' value="${current#' . $prefix . '=}"' . "\n" . ' COMPREPLY=( $(compgen -W ' . self::quote(self::words($values)) . ' -P ' . self::quote($prefix . '=') . ' -- "$value") )' . "\n" . " return\n ;;\n"; } foreach (CompletionMetadata::directoryEqualsOptions() as $option) { $prefix = substr($option, 0, -1); $equalsCases .= ' ' . self::bashPattern($prefix) . "=*)\n" . ' value="${current#' . $prefix . '=}"' . "\n" . " compopt -o filenames\n" . ' COMPREPLY=()' . "\n" . ' while IFS= read -r candidate; do' . "\n" . ' COMPREPLY+=("' . $prefix . '=${candidate}")' . "\n" . ' done < <(compgen -d -- "$value")' . "\n" . " return\n ;;\n"; } $script = << 0 )); then previous="\${COMP_WORDS[COMP_CWORD - 1]}" fi local index for ((index = 1; index < COMP_CWORD; index++)); do if [[ "\${COMP_WORDS[index]}" == -- ]]; then compopt -o default return fi done case "\$previous" in {$valueCases} {$directoryOptions}) compopt -o filenames _typephp_tpc_complete_paths -d "\$current" return ;; {$pythonFileOptions}) compopt -o filenames _typephp_tpc_complete_python_files "\$current" return ;; {$outputFileOptions}) compopt -o filenames _typephp_tpc_complete_paths -f "\$current" return ;; esac case "\$current" in -O[0-3]) COMPREPLY=("\$current") return ;; -O*) value="\${current#-O}" COMPREPLY=( $(compgen -W '0 1 2 3' -P '-O' -- "\$value") ) return ;; {$equalsCases} -* ) COMPREPLY=( $(compgen -W {$quotedOptions} -- "\$current") ) return ;; esac compopt -o filenames _typephp_tpc_complete_files "\$current" } complete -F _typephp_tpc tpc complete -F _typephp_tpc ./tpc complete -F _typephp_tpc tpc.php complete -F _typephp_tpc bin/tpc.php complete -F _typephp_tpc ./bin/tpc.php BASH; return $script . PHP_EOL; } /** @param list $words */ private static function words(array $words): string { return implode(' ', $words); } private static function quote(string $value): string { return "'" . str_replace("'", "'\\''", $value) . "'"; } private static function bashPattern(string $value): string { return str_replace(['\\', '*', '?', '[', ']'], ['\\\\', '\\*', '\\?', '\\[', '\\]'], $value); } }