From 58ef8a8f42a68c7a81118ef9120705730ce3f458 Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Sat, 11 Apr 2026 16:50:57 +0800 Subject: Add shell completion script generation feature --- mingling_core/tmpls/comps/bash.sh | 48 ++++++++++++++ mingling_core/tmpls/comps/fish.fish | 128 ++++++++++++++++++++++++++++++++++++ mingling_core/tmpls/comps/pwsl.ps1 | 43 ++++++++++++ mingling_core/tmpls/comps/zsh.zsh | 68 +++++++++++++++++++ 4 files changed, 287 insertions(+) create mode 100644 mingling_core/tmpls/comps/bash.sh create mode 100644 mingling_core/tmpls/comps/fish.fish create mode 100644 mingling_core/tmpls/comps/pwsl.ps1 create mode 100644 mingling_core/tmpls/comps/zsh.zsh (limited to 'mingling_core/tmpls') diff --git a/mingling_core/tmpls/comps/bash.sh b/mingling_core/tmpls/comps/bash.sh new file mode 100644 index 0000000..1af4f6c --- /dev/null +++ b/mingling_core/tmpls/comps/bash.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +_<<>>_bash_completion() { + local cur="${COMP_WORDS[COMP_CWORD]}" + local prev="" + [ $COMP_CWORD -gt 0 ] && prev="${COMP_WORDS[COMP_CWORD-1]}" + + local word_index=$((COMP_CWORD + 1)) + + local args=() + args+=(-f="${COMP_LINE//-/^}") + args+=(-C="$COMP_POINT") + args+=(-w="${cur//-/^}") + args+=(-p="${prev//-/^}") + args+=(-c="${COMP_WORDS[0]//-/^}") + args+=(-i="$word_index") + args+=(-F="bash") + + for word in "${COMP_WORDS[@]}"; do + args+=(-a="${word//-/^}") + done + + local suggestions + if suggestions=$(<<>> __comp "${args[@]}" 2>/dev/null); then + if [ $? -eq 0 ]; then + if [ "$suggestions" = "_file_" ]; then + compopt -o default + COMPREPLY=() + return + fi + + if [ -n "$suggestions" ]; then + local -a all_suggestions filtered + mapfile -t all_suggestions < <(printf '%s\n' "$suggestions") + + for suggestion in "${all_suggestions[@]}"; do + [ -z "$cur" ] || [[ "$suggestion" == "$cur"* ]] && filtered+=("$suggestion") + done + + [ ${#filtered[@]} -gt 0 ] && COMPREPLY=("${filtered[@]}") + return + fi + fi + fi + + COMPREPLY=() +} + +complete -F _<<>>_bash_completion <<>> diff --git a/mingling_core/tmpls/comps/fish.fish b/mingling_core/tmpls/comps/fish.fish new file mode 100644 index 0000000..8be948a --- /dev/null +++ b/mingling_core/tmpls/comps/fish.fish @@ -0,0 +1,128 @@ +#!/usr/bin/env fish +function __<<>>_fish_complete + set -l cmdline (commandline -opc) + set -l buffer (commandline -b) + set -l cursor (commandline -C) + set -l current_token (commandline -ct) + + # Calculate current word and word index + set -l current_word "" + set -l previous_word "" + set -l word_index 0 + set -l char_count 0 + + set -l found false + if test -n "$current_token" + for i in (seq (count $cmdline)) + if test "$cmdline[$i]" = "$current_token" + set word_index $i + set current_word $current_token + if test $i -gt 1 + set previous_word $cmdline[(math $i - 1)] + end + set found true + break + end + end + end + + if not $found + for i in (seq (count $cmdline)) + set word $cmdline[$i] + if test $i -gt 1 + set char_count (math $char_count + 1) + end + set char_count (math $char_count + (string length -- "$word")) + + if test $cursor -le $char_count + set word_index $i + set current_word $word + if test $i -gt 1 + set previous_word $cmdline[(math $i - 1)] + end + break + end + end + end + + # Handle cursor after last word + if test $word_index -eq 0 -a (count $cmdline) -gt 0 + set word_index (count $cmdline) + if test -n "$current_token" -a "$current_token" != "$cmdline[-1]" + set current_word $current_token + else + set current_word "" + end + set previous_word $cmdline[-1] + end + + # Ensure word_index is within bounds + if test $word_index -gt (count $cmdline) + set word_index (count $cmdline) + end + + # Replace hyphens with carets for jvn_comp + set -l buffer_replaced (string replace -a "-" "^" -- "$buffer") + set -l current_word_replaced (string replace -a "-" "^" -- "$current_word") + set -l previous_word_replaced (string replace -a "-" "^" -- "$previous_word") + + # Build args array + set -l args + set -a args -f "$buffer_replaced" -C "$cursor" -w "$current_word_replaced" -p "$previous_word_replaced" + + if test (count $cmdline) -gt 0 + set -a args -c "$cmdline[1]" + else + set -a args -c "" + end + + set -a args -i "$word_index" + + # Replace hyphens in all words + if test (count $cmdline) -gt 0 + set -l all_words_replaced + for word in $cmdline + set -a all_words_replaced (string replace -a "-" "^" -- "$word") + end + + if test -n "$current_token" -a "$current_word" = "$current_token" + set -l found_in_cmdline false + for word in $cmdline + if test "$word" = "$current_token" + set found_in_cmdline true + break + end + end + if not $found_in_cmdline -a $word_index -eq (math (count $cmdline) + 1) + set -a all_words_replaced (string replace -a "-" "^" -- "$current_token") + end + end + + set -a args -a $all_words_replaced + else + set -a args -a "" + end + + # Add shell type argument + set -a args -F "fish" + + # Call jvn_comp and handle output + set -l output + if not <<>> __comp $args 2>/dev/null | read -z output + return + end + + set -l trimmed_output (string trim -- "$output") + if test "$trimmed_output" = "_file_" + __fish_complete_path "$current_word" + return 0 + else if test -n "$trimmed_output" + string split -n \n -- "$output" | while read -l line + test -n "$line" && echo "$line" + end + return 0 + end + return 1 +end + +complete -c <<>> -a '(__<<>>_fish_complete)' -f diff --git a/mingling_core/tmpls/comps/pwsl.ps1 b/mingling_core/tmpls/comps/pwsl.ps1 new file mode 100644 index 0000000..6d7d91d --- /dev/null +++ b/mingling_core/tmpls/comps/pwsl.ps1 @@ -0,0 +1,43 @@ +Register-ArgumentCompleter -CommandName <<>> -ScriptBlock { + param($wordToComplete, $commandAst, $cursorPosition) + + $line = $commandAst.ToString() + $commandName = if ($commandAst.CommandElements.Count -gt 0) { + $commandAst.CommandElements[0].Value + } else { "" } + + $words = @() + $currentIndex = 0 + $parser = [System.Management.Automation.PSParser] + $tokens = $parser::Tokenize($line, [ref]$null) + + foreach ($token in $tokens) { + if ($token.Type -in 'CommandArgument', 'CommandParameter') { + $words += $token.Content + } + } + + $args = @( + "-f", ($line -replace '-', '^') + "-C", $cursorPosition.ToString() + "-w", ($wordToComplete -replace '-', '^') + "-p", (if ($words.Count -gt 1) { $words[-2] } else { "" }) -replace '-', '^' + "-c", $commandName + "-i", ($words.Count - 1).ToString() + "-a", ($words | ForEach-Object { $_ -replace '-', '^' }) + "-F", "powershell" + ) + + $suggestions = <<>> __comp $args 2>$null + + if ($suggestions) { + $suggestions | ForEach-Object { + if ($_ -eq "_file_") { + $completionType = 'ProviderItem' + } else { + $completionType = 'ParameterValue' + } + [System.Management.Automation.CompletionResult]::new($_, $_, $completionType, $_) + } + } +} diff --git a/mingling_core/tmpls/comps/zsh.zsh b/mingling_core/tmpls/comps/zsh.zsh new file mode 100644 index 0000000..c1c18bb --- /dev/null +++ b/mingling_core/tmpls/comps/zsh.zsh @@ -0,0 +1,68 @@ +#!/usr/bin/env zsh +_<<>>_completion() { + local -a args + local suggestions + + local buffer="$BUFFER" + local cursor="$CURSOR" + local current_word="${words[$CURRENT]}" + local previous_word="" + local command_name="${words[1]}" + local word_index="$CURRENT" + + if [[ $CURRENT -gt 1 ]]; then + previous_word="${words[$((CURRENT-1))]}" + fi + + args=( + -f "${buffer//-/^}" + -C "$cursor" + -w "${current_word//-/^}" + -p "${previous_word//-/^}" + -c "$command_name" + -i "$word_index" + -a "${(@)words//-/^}" + -F "zsh" + ) + + suggestions=$(<<>> __comp "${args[@]}" 2>/dev/null) + + if [[ $? -eq 0 ]] && [[ -n "$suggestions" ]]; then + local -a completions + completions=(${(f)suggestions}) + + if [[ "${completions[1]}" == "_file_" ]]; then + shift completions + _files + else + local -a parsed_completions + for item in "${completions[@]}"; do + if [[ "$item" =~ '^([^$]+)\$\((.+)\)$' ]]; then + parsed_completions+=("${match[1]}:${match[2]}") + else + parsed_completions+=("$item") + fi + done + + if (( $+functions[_describe] )); then + _describe '<<>> commands' parsed_completions + else + local -a simple_completions + for item in "${parsed_completions[@]}"; do + if [[ "$item" =~ '^([^:]+):(.+)$' ]]; then + simple_completions+=("${match[1]}") + else + simple_completions+=("$item") + fi + done + compadd -a simple_completions + fi + fi + fi +} + +compdef _<<>>_completion <<>> + +if [[ $? -ne 0 ]]; then + compctl -K _<<>>_completion <<>> +fi -- cgit