From 6fa3f737e2c33555a55e65abf38d5809a4815014 Mon Sep 17 00:00:00 2001 From: Jonathan Hodgson Date: Tue, 4 Oct 2022 11:42:47 +0100 Subject: [PATCH] Work on openapi completion Currently still a work in progress. the bin/.bin/openapi file will be a bash script for interfacing with an openapi file. Currently it does things like listing requests, servers, and viewing a request in json format. The function added to fzf.zsh adds a zsh widget so that I can press a keybinding (in my case ^o) to complete the command. It uses the above script and fzf to make the selection. Currently supports http / https / curl The widget looks for an environment variable called OPENAPI which should point to the openapi file. This is set in zshrc if a project is set. --- bin/.bin/openapi | 97 +++++++++++++++++++++++++++++++++++++ shells/zsh/STOW/.zshrc | 1 + shells/zsh/includes/fzf.zsh | 19 ++++++++ 3 files changed, 117 insertions(+) create mode 100755 bin/.bin/openapi diff --git a/bin/.bin/openapi b/bin/.bin/openapi new file mode 100755 index 00000000..a01e6a9c --- /dev/null +++ b/bin/.bin/openapi @@ -0,0 +1,97 @@ +#!/usr/bin/env bash + +print_help(){ + echo "Help: todo" +} + +echo_header(){ + [ -n "$header" ] && echo "$@" +} + +# Gets requests in a json format where each request method is a top level item +get_requests(){ + cat "$json" | jq -r '.paths | to_entries | .[] | .key as $slug | .value | to_entries | map_values({slug: $slug, method: .key} + .value) | .[]' +} + +list_requests(){ + echo_header -e "Method\tSlug\tSummary" + get_requests | jq -r '[.method, .slug, .summary] | @tsv' +} + +list_servers(){ + echo_header -e "Url" + cat "$json" | jq -r '.servers[].url' +} + +list_urls(){ + for server in $(list_servers); do + for path in $(list_requests | cut -d $'\t' -f 2 | sort -u ); do + echo "$server$path" + done + done +} + +view_request(){ + path="$1" + method="${2:-get}" + path="$(echo "$path" | tr 'A-Z' 'a-z')" + method="$(echo "$method" | tr 'A-Z' 'a-z')" + for server in $(list_servers); do + path="$(echo "$path" | sed "s#^$server##")" + done + #get_requests | jq --slurp ".[]" + get_requests | jq ". | select( .slug | ascii_downcase == \"${path}\" ) | select( .method | ascii_downcase == \"${method}\" )" +} + +unset options +while (($#)); do + case $1 in + # If option is of type -ab + -[!-]?*) + # Loop over each character starting with the second + for ((i=1; i < ${#1}; i++)); do + c=${1:i:1} + + # Add current char to options + options+=("-$c") + + done + ;; + + # If option is of type --foo=bar + --?*=*) options+=("${1%%=*}" "${1#*=}") ;; + # add --endopts for -- + --) options+=(--endopts) ;; + # Otherwise, nothing special + *) options+=("$1") ;; + esac + shift +done +set -- "${options[@]}" +unset options + +# Print help if no arguments were passed. +# Uncomment to force arguments when invoking the script +[[ $# -eq 0 ]] && set -- "--help" + +json="" +header="" + +# Read the options and set stuff +while [[ $1 = -?* ]]; do + case $1 in + -h|--help) print_help >&2 ;; + --json|-j) json="$2"; shift ;; + --header) header="yes" ;; + *) echo "Unknown option $1"; print_help >&2 ;; + esac + shift +done + + +case "$1" in + requests) list_requests ;; + servers) list_servers ;; + urls) list_urls ;; + request) shift; view_request "$@" +esac diff --git a/shells/zsh/STOW/.zshrc b/shells/zsh/STOW/.zshrc index 8a2d0ed8..56449d95 100644 --- a/shells/zsh/STOW/.zshrc +++ b/shells/zsh/STOW/.zshrc @@ -72,6 +72,7 @@ else if [[ ! "$(ps -ocommand -p $PPID | grep -v 'COMMAND' | cut -d' ' -f1 )" == "$script" ]]; then if [ -f "$current/index.yaml" ]; then export repdef="$(realpath "$current/$(yq -r .repdef "$current/index.yaml")")" + export OPENAPI="$(realpath "$current/$(yq -r .openapi "$current/index.yaml")")" fi mkdir "$current/shell-logs" 2> /dev/null /usr/bin/script -f "$current/shell-logs/$(date +"%d-%b-%y_%H-%M-%S")_shell.log" diff --git a/shells/zsh/includes/fzf.zsh b/shells/zsh/includes/fzf.zsh index c52296c3..b33507c8 100644 --- a/shells/zsh/includes/fzf.zsh +++ b/shells/zsh/includes/fzf.zsh @@ -152,4 +152,23 @@ if [ "$sourced" = "True" ]; then bind-git-helper f b t r h s unset -f bind-git-helper + fzf-openapi-widget(){ + if [ -n "$OPENAPI" ] && [ -f "$OPENAPI" ]; then + server="$(openapi -j "$OPENAPI" servers | fzf -1 --prompt Server)" + request="$(openapi -j "$OPENAPI" requests | column -t -s $'\t' | fzf -d ' +' --height 90% --preview "openapi -j \"$OPENAPI\" request {2} {1} | jq -C '.'")" + method="$(echo -n "$request" | awk -F ' +' '{print $1}' | tr 'a-z' 'A-Z')" + url="$(echo -n "$request" | awk -F ' +' '{print $2}')" + + case "$LBUFFER" in + http*|https*) LBUFFER+=" $method $server$url" ;; + curl*) LBUFFER+=" -X $method $server$url" ;; + esac + LBUFFER="$(echo -n "$LBUFFER" | sed -E 's/ +/ /g')" + zle reset-prompt + fi + } + zle -N fzf-openapi-widget + bindkey '^o' fzf-openapi-widget + + fi