def bash_engine
cli@0.2.0.0 · cli.bend:6603
import cli@0.2.0.0/cli.bend as Cli
import Base
6603
6604
6605def bash_engine(+id: String, name: String) -> List<&2, String>:
6606 [
6607 "",
6608 "# Offers each value of kind that starts with $1, written after $2 and cut to",
6609 "# the part readline completes: the text after the last \"=\" or \":\". Readline",
6610 "# quotes files and directories; words are quoted here.",
6611 String.concat([id, "_offer() {"]),
6612 " local word full i",
6613 " case $kind in",
6614 " f) compopt -o filenames; mapfile -t values < <(compgen -f -- \"$1\") ;;",
6615 " d) compopt -o filenames; mapfile -t values < <(compgen -d -- \"$1\") ;;",
6616 " w)",
6617 " for ((i = 0; i < ${#values[@]}; i++)); do",
6618 " printf -v 'values[i]' %q \"${values[i]}\"",
6619 " done ;;",
6620 " *) return ;;",
6621 " esac",
6622 " for word in \"${values[@]}\"; do",
6623 " full=$2$word",
6624 " [[ $word == \"$1\"* ]] && COMPREPLY+=(\"${full:${#2}+${#1}-${#tail}}\")",
6625 " done",
6626 "}",
6627 "",
6628 String.concat([id, "() {"]),
6629 " local -a words=() opts=() subs=() dests=() values=()",
6630 " local cur tail word line gap path= want= kind opt many rest i j n=0 end=0 help=0",
6631 " COMPREPLY=()",
6632 " # Rejoin the \"=\" and \":\" that bash splits words at. COMP_LINE has no blank",
6633 " # at such a split, so a \"=\" typed as its own word stays one.",
6634 " line=${COMP_LINE#*\"${COMP_WORDS[0]}\"}",
6635 " for ((i = 1; i <= COMP_CWORD; i++)); do",
6636 " word=${COMP_WORDS[i]}",
6637 " tail=${COMP_WORDS[i-1]}",
6638 " gap=${line%%[![:blank:]]*}",
6639 " line=${line:${#gap}+${#word}}",
6640 " if ((i > 1)) && [[ -z $gap ]] &&",
6641 " [[ -n $word && -z ${word//[=:]} || -n $tail && -z ${tail//[=:]} ]]; then",
6642 " words[${#words[@]}-1]+=$word",
6643 " else",
6644 " words+=(\"$word\")",
6645 " fi",
6646 " done",
6647 " tail=${COMP_WORDS[COMP_CWORD]}",
6648 " [[ -z ${tail//[=:]} ]] && tail=",
6649 " cur=${words[${#words[@]}-1]}",
6650 " unset 'words[${#words[@]}-1]'",
6651 String.concat([" ", id, "_scope"]),
6652 " for word in \"${words[@]}\"; do",
6653 " if [[ -n $want ]]; then",
6654 " want=",
6655 " elif ((!end)) && [[ $word == -- ]]; then",
6656 " end=1",
6657 " elif ((!end)) && [[ $word == --* ]]; then",
6658 String.concat([" ", id, "_arg \"${word%%=*}\""]),
6659 " [[ -n $kind && $opt == 0 && $word != *=* ]] && want=$word",
6660 " elif ((!end)) && [[ $word == -?* ]]; then",
6661 " for ((j = 1; j < ${#word}; j++)); do",
6662 String.concat([" ", id, "_arg \"-${word:j:1}\""]),
6663 " [[ -n $kind ]] || continue",
6664 " ((j + 1 == ${#word})) && want=-${word:j:1}",
6665 " break",
6666 " done",
6667 " elif ((${#subs[@]})); then",
6668 " ((end)) && return",
6669 " if [[ $word == help ]] && ((!help)); then",
6670 " help=1",
6671 " continue",
6672 " fi",
6673 " for ((j = 0; j < ${#subs[@]}; j++)); do",
6674 " [[ $word == \"${subs[j]}\" ]] && break",
6675 " done",
6676 " ((j < ${#subs[@]})) || return",
6677 " path=${dests[j]}",
6678 String.concat([" ", id, "_scope"]),
6679 " else",
6680 " # n counts the slots filled. The variadic slot stays open, but a rest()",
6681 " # value takes every later word, so nothing more completes.",
6682 " n=$((n + 1))",
6683 " if ((n == many && rest)); then",
6684 " end=1",
6685 " elif ((n == many)); then",
6686 " n=$((n - 1))",
6687 " fi",
6688 " fi",
6689 " done",
6690 " if [[ -n $want ]]; then",
6691 String.concat([" ", id, "_arg \"$want\""]),
6692 String.concat([" ", id, "_offer \"$cur\" ''"]),
6693 " elif ((!end)) && [[ $cur == --*=* ]]; then",
6694 String.concat([" ", id, "_arg \"${cur%%=*}\""]),
6695 String.concat([" ", id, "_offer \"${cur#*=}\" \"${cur%%=*}=\""]),
6696 " elif ((!end)) && [[ $cur == -* ]]; then",
6697 " values=(\"${opts[@]}\") kind=w",
6698 " ((help)) && values=('-h' '--help')",
6699 String.concat([" ", id, "_offer \"$cur\" ''"]),
6700 " elif ((!end && ${#subs[@]})); then",
6701 " values=(\"${subs[@]}\") kind=w",
6702 " ((help)) || values+=('help')",
6703 String.concat([" ", id, "_offer \"$cur\" ''"]),
6704 " elif ((!help)); then",
6705 String.concat([" ", id, "_arg $((n + 1))"]),
6706 String.concat([" ", id, "_offer \"$cur\" ''"]),
6707 " fi",
6708 "}",
6709 "",
6710 String.concat(["complete -F ", id, " ", name]),
6711 ]