From 1f10109481f3a53c846f0e0f5b39d1cb9875be6a Mon Sep 17 00:00:00 2001 From: Maarten Billemont Date: Thu, 12 Mar 2015 01:03:02 -0400 Subject: [PATCH] A bash completion script for mpw. --- bashcomplib | 61 +++++++++++++++++++++++++++++++++++++++++++++ mpw.completion.bash | 56 +++++++++++++++++++++++++++++++++++++++++ src/mpw-algorithm.h | 1 + 3 files changed, 118 insertions(+) create mode 100644 bashcomplib create mode 100644 mpw.completion.bash diff --git a/bashcomplib b/bashcomplib new file mode 100644 index 0000000..367e415 --- /dev/null +++ b/bashcomplib @@ -0,0 +1,61 @@ +#!/usr/bin/env bash + +# FIXME +# partials are currently readline words, but these can't be reliably compared against literal data. We need to make them literal first.. in a safe way. Currently using xargs' quote parser as a hack. + +# Process literal completion options in COMPREPLY +# +# 1. Filter COMPREPLY by excluding the options that do not match the word that is being completed. +# 2. Shell-escape the COMPREPLY words so they remain syntactical words when injected into the completed command. +# 3. Add a space after the words so successful completions advance to the next word +# (we disabled this default behavior with -o nospace so we can do completions that don't want this, eg. directory names) +_comp_finish_completions() { + local partial=$(xargs <<< "${COMP_WORDS[COMP_CWORD]}") # FIXME + local word words=( "${COMPREPLY[@]}" ) + + COMPREPLY=() + for word in "${words[@]}"; do + ( shopt -s nocasematch; [[ $word = $partial* ]] ) && COMPREPLY+=( "$(printf '%q ' "$word")" ) + done + + if (( ${#COMPREPLY[@]} > 1 )) && [[ $_comp_title ]]; then + printf '\n%s:' "$_comp_title" + unset _comp_title + fi +} + +# Perform pathname completion. +# +# 1. Populate COMPREPLY with pathnames. +# 2. Shell-escape the COMPREPLY words so they remain syntactical words when injected into the completed command. +# 3. Add a space after file names so successful completions advance to the next word. +# Directory names are suffixed with a / instead so we can keep completing the files inside. +_comp_complete_path() { + local partial=$(xargs <<< "${COMP_WORDS[COMP_CWORD]}") + local path + + COMPREPLY=() + for path in "$partial"*; do + if [[ -d $path ]]; then + COMPREPLY+=( "$(printf '%q/' "$path")" ) + + elif [[ -e $path ]]; then + COMPREPLY+=( "$(printf '%q ' "$path")" ) + + fi + done +} + +_show_args() { + echo + local i=0 + for arg; do + printf "arg %d: %s\n" "$((i++))" "$arg" + done + + i=0 + for word in "${COMP_WORDS[@]}"; do + printf "word %d: %s -> %s %s\n" "$i" "$word" "$(xargs <<< "$word")" "$( ((i == $COMP_CWORD)) && echo '' )" + let i++ + done +} diff --git a/mpw.completion.bash b/mpw.completion.bash new file mode 100644 index 0000000..38943a8 --- /dev/null +++ b/mpw.completion.bash @@ -0,0 +1,56 @@ +#!/usr/bin/env bash +source bashcomplib + +# completing the 'mpw' command. +_comp_mpw() { + local optarg= cword=${COMP_WORDS[COMP_CWORD]} pcword + + if (( COMP_CWORD > 0 )); then + pcword=${COMP_WORDS[COMP_CWORD - 1]} + + case $pcword in + -u) optarg=user ;; + -t) optarg=type ;; + -c) optarg=counter ;; + -V) optarg=version ;; + -v) optarg=variant ;; + -C) optarg=context ;; + esac + fi + + case $optarg in + user) # complete full names. + COMPREPLY=( ~/.mpw.d/*.mpsites ) COMPREPLY=( "${COMPREPLY[@]##*/}" ) COMPREPLY=( "${COMPREPLY[@]%.mpsites}" ) + ;; + type) # complete types. + COMPREPLY=( maximum long medium basic short pin name phrase ) + ;; + counter) # complete counter. + COMPREPLY=( 1 ) + ;; + version) # complete versions. + COMPREPLY=( 0 1 2 3 ) + ;; + variant) # complete variants. + COMPREPLY=( password login answer ) + ;; + context) # complete context. + ;; + *) + # previous word is not an option we can complete, complete site name (or option if leading -) + if [[ $cword = -* ]]; then + COMPREPLY=( -u -t -c -V -v -C ) + else + local w fullName=$MP_FULLNAME + for (( w = 0; w < ${#COMP_WORDS[@]}; ++w )); do + [[ ${COMP_WORDS[w]} = -u ]] && fullName=$(xargs <<< "${COMP_WORDS[w + 1]}") && break + done + IFS=$'\n' read -d '' -ra COMPREPLY < <(awk -F$'\t' '!/^ *#/{sub(/^ */, "", $2); print $2}' ~/.mpw.d/"$fullName.mpsites") + printf -v _comp_title 'Sites for %s' "$fullName" + fi ;; + esac + _comp_finish_completions +} + +#complete -F _show_args mpw +complete -o nospace -F _comp_mpw mpw diff --git a/src/mpw-algorithm.h b/src/mpw-algorithm.h index 71fb0a0..dab72e7 100644 --- a/src/mpw-algorithm.h +++ b/src/mpw-algorithm.h @@ -6,6 +6,7 @@ // Copyright (c) 2014 Lyndir. All rights reserved. // +// NOTE: mpw is currently NOT thread-safe. #include "mpw-types.h" typedef enum(unsigned int, MPAlgorithmVersion) {