From f61fbdecf2b9b9c998af300f569c9b87dbaf9bc0 Mon Sep 17 00:00:00 2001 From: felixlohmeier Date: Fri, 7 Oct 2022 10:57:11 +0000 Subject: [PATCH 1/2] first draft batch --interactive --- orcli | 73 ++++++++++++++++++++++++++++++------- src/bashly.yml | 3 ++ src/batch_command.sh | 34 +++++++++++------ src/lib/interactive.sh | 16 ++++++++ src/lib/send_completions.sh | 2 +- 5 files changed, 103 insertions(+), 25 deletions(-) create mode 100644 src/lib/interactive.sh diff --git a/orcli b/orcli index 12566a1..c248f14 100755 --- a/orcli +++ b/orcli @@ -157,6 +157,11 @@ orcli_batch_usage() { printf " Default: 3333\n" echo + # :flag.usage + echo " --interactive" + printf " provide interactive Bash shell for playground and debugging\n" + echo + # :command.usage_args printf "Arguments:\n" @@ -168,6 +173,7 @@ orcli_batch_usage() { # :command.usage_examples printf "Examples:\n" + printf " orcli batch --interactive\n" printf " orcli batch << EOF\n orcli import csv \"https://git.io/fj5hF\" --projectName \"duplicates\"\n orcli info \"duplicates\"\n orcli export tsv \"duplicates\"\n EOF\n" printf " orcli batch --memory \"2000M\" --port \"3334\" << EOF\n orcli import csv \"https://git.io/fj5hF\" --projectName \"duplicates\" &\n orcli import csv \"https://git.io/fj5hF\" --projectName \"copy\" &\n wait\n echo \"finished import\"\n orcli export csv \"duplicates\" --output duplicates.csv &\n orcli export tsv \"duplicates\" --output duplicates.tsv &\n wait\n wc duplicates*\n EOF\n" printf " orcli batch \"file1.sh\" \"file2.sh\" - << EOF\n echo \"finished in \$SECONDS seconds\"\n EOF\n" @@ -579,6 +585,24 @@ function init_import() { fi } +# src/lib/interactive.sh +# shellcheck shell=bash +function interactive() { + cat <<'EOF' +if ! command -v orcli &>/dev/null; then + alias orcli="$orcli" +fi +PS1="(orcli) [\u@\h \W]\$ " +source <(orcli completions) +echo '================================================================' +echo 'Interactive Bash shell with OpenRefine running in the background' +echo 'Use the "orcli" command and tab completion to control OpenRefine' +echo 'Type "history -a FILE" to write out your session history' +echo 'Type "exit" or CTRL-D to destroy temporary OpenRefine workspace' +echo '================================================================' +EOF +} + # src/lib/logging.sh # print messages to STDERR # shellcheck shell=bash @@ -680,7 +704,7 @@ send_completions() { echo $' ;;' echo $'' echo $' \'batch\'*)' - echo $' while read -r; do COMPREPLY+=( "$REPLY" ); done < <( compgen -W "$(_orcli_completions_filter "--help --memory --port -h")" -- "$cur" )' + echo $' while read -r; do COMPREPLY+=( "$REPLY" ); done < <( compgen -W "$(_orcli_completions_filter "--help --interactive --memory --port -h")" -- "$cur" )' echo $' ;;' echo $'' echo $' \'list\'*)' @@ -706,19 +730,24 @@ send_completions() { # :command.function orcli_completions_command() { # src/completions_command.sh - # shellcheck shell=bash disable=SC2154 + # Users can now enable bash completion for this script by running: + # + # $ eval "$(orcli completions)" + # send_completions } # :command.function orcli_batch_command() { # src/batch_command.sh - # shellcheck shell=bash disable=SC2154 + # shellcheck shell=bash disable=SC2154 source=/dev/null # check if stdin is present if selected - if [[ ${args[file]} == '-' ]] || [[ ${args[file]} == '"-"' ]] && [ -t 0 ]; then - orcli_batch_usage - exit 1 + if ! [[ ${args[--interactive]} ]]; then + if [[ ${args[file]} == '-' ]] || [[ ${args[file]} == '"-"' ]] && [ -t 0 ]; then + orcli_batch_usage + exit 1 + fi fi # catch args, convert the space delimited string to an array @@ -729,12 +758,12 @@ orcli_batch_command() { OPENREFINE_URL="http://localhost:${args[--port]}" # locate orcli and OpenRefine - if command -v orcli &>/dev/null; then - orcli="orcli" - elif [[ -x "orcli" ]]; then - orcli="./orcli" - else - error "orcli is not executable!" "Try: chmod + ./orcli" + if ! command -v orcli &>/dev/null; then + if [[ -x "$0" ]]; then + orcli="$0" + else + error "orcli is not executable!" "Try: chmod + $0" + fi fi if [[ -x "refine" ]]; then openrefine="./refine" @@ -767,7 +796,17 @@ orcli_batch_command() { # execute shell script export orcli tmpdir OPENREFINE_URL openrefine_pid - bash -e <(awk 1 "${files[@]}") + if [[ ${args[--interactive]} ]]; then + bash --rcfile <( + cat ~/.bashrc + interactive + if ! [[ ${args[file]} == '-' || ${args[file]} == '"-"' ]]; then + awk 1 "${files[@]}" + fi + ) -i + else + bash -e <(awk 1 "${files[@]}") + fi } @@ -1082,6 +1121,14 @@ orcli_batch_parse_requirements() { fi ;; + # :flag.case + --interactive ) + + # :flag.case_no_arg + args[--interactive]=1 + shift + ;; + -?* ) printf "invalid option: %s\n" "$key" >&2 exit 1 diff --git a/src/bashly.yml b/src/bashly.yml index 7858cf0..357cecd 100644 --- a/src/bashly.yml +++ b/src/bashly.yml @@ -52,7 +52,10 @@ commands: help: PORT on which OpenRefine should listen arg: port default: "3333" + - long: --interactive + help: provide interactive Bash shell for playground and debugging examples: + - orcli batch --interactive - |- orcli batch << EOF orcli import csv "https://git.io/fj5hF" --projectName "duplicates" diff --git a/src/batch_command.sh b/src/batch_command.sh index 0398a0e..e966f14 100644 --- a/src/batch_command.sh +++ b/src/batch_command.sh @@ -1,9 +1,11 @@ -# shellcheck shell=bash disable=SC2154 +# shellcheck shell=bash disable=SC2154 source=/dev/null # check if stdin is present if selected -if [[ ${args[file]} == '-' ]] || [[ ${args[file]} == '"-"' ]] && [ -t 0 ]; then - orcli_batch_usage - exit 1 +if ! [[ ${args[--interactive]} ]]; then + if [[ ${args[file]} == '-' ]] || [[ ${args[file]} == '"-"' ]] && [ -t 0 ]; then + orcli_batch_usage + exit 1 + fi fi # catch args, convert the space delimited string to an array @@ -14,12 +16,12 @@ eval "files=(${args[file]})" OPENREFINE_URL="http://localhost:${args[--port]}" # locate orcli and OpenRefine -if command -v orcli &>/dev/null; then - orcli="orcli" -elif [[ -x "orcli" ]]; then - orcli="./orcli" -else - error "orcli is not executable!" "Try: chmod + ./orcli" +if ! command -v orcli &>/dev/null; then + if [[ -x "$0" ]]; then + orcli="$0" + else + error "orcli is not executable!" "Try: chmod + $0" + fi fi if [[ -x "refine" ]]; then openrefine="./refine" @@ -52,4 +54,14 @@ fi # execute shell script export orcli tmpdir OPENREFINE_URL openrefine_pid -bash -e <(awk 1 "${files[@]}") +if [[ ${args[--interactive]} ]]; then + bash --rcfile <( + cat ~/.bashrc + interactive + if ! [[ ${args[file]} == '-' || ${args[file]} == '"-"' ]]; then + awk 1 "${files[@]}" + fi + ) -i +else + bash -e <(awk 1 "${files[@]}") +fi diff --git a/src/lib/interactive.sh b/src/lib/interactive.sh new file mode 100644 index 0000000..9ae432e --- /dev/null +++ b/src/lib/interactive.sh @@ -0,0 +1,16 @@ +# shellcheck shell=bash +function interactive() { + cat <<'EOF' +if ! command -v orcli &>/dev/null; then + alias orcli="$orcli" +fi +PS1="(orcli) [\u@\h \W]\$ " +source <(orcli completions) +echo '================================================================' +echo 'Interactive Bash shell with OpenRefine running in the background' +echo 'Use the "orcli" command and tab completion to control OpenRefine' +echo 'Type "history -a FILE" to write out your session history' +echo 'Type "exit" or CTRL-D to destroy temporary OpenRefine workspace' +echo '================================================================' +EOF +} diff --git a/src/lib/send_completions.sh b/src/lib/send_completions.sh index a379d57..32485a5 100644 --- a/src/lib/send_completions.sh +++ b/src/lib/send_completions.sh @@ -51,7 +51,7 @@ send_completions() { echo $' ;;' echo $'' echo $' \'batch\'*)' - echo $' while read -r; do COMPREPLY+=( "$REPLY" ); done < <( compgen -W "$(_orcli_completions_filter "--help --memory --port -h")" -- "$cur" )' + echo $' while read -r; do COMPREPLY+=( "$REPLY" ); done < <( compgen -W "$(_orcli_completions_filter "--help --interactive --memory --port -h")" -- "$cur" )' echo $' ;;' echo $'' echo $' \'list\'*)' From 8144831bf7c25fff61ebe629fc16ee7ac3a711c4 Mon Sep 17 00:00:00 2001 From: felixlohmeier Date: Sat, 15 Oct 2022 20:57:07 +0000 Subject: [PATCH 2/2] support stdin --- orcli | 64 ++++++++++++++++++++----------------- src/bashly.yml | 7 ++-- src/batch_command.sh | 37 +++++++++++---------- src/import_csv_command.sh | 8 +++-- src/lib/send_completions.sh | 2 +- 5 files changed, 65 insertions(+), 53 deletions(-) diff --git a/orcli b/orcli index c248f14..ae6095a 100755 --- a/orcli +++ b/orcli @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# This script was generated by bashly 0.8.7 (https://bashly.dannyb.co) +# This script was generated by bashly 0.8.9 (https://bashly.dannyb.co) # Modifying it manually is not recommended # :wrapper.bash3_bouncer @@ -35,7 +35,7 @@ orcli_usage() { # :command.usage_commands printf "Commands:\n" echo " completions Generate bash completions" - echo " batch run tmp OpenRefine workspace and execute shell script" + echo " batch run tmp OpenRefine workspace and execute shell script(s)" echo " import import commands" echo " list list projects on OpenRefine server" echo " info show project metadata" @@ -121,11 +121,11 @@ orcli_completions_usage() { # :command.usage orcli_batch_usage() { if [[ -n $long_usage ]]; then - printf "orcli batch - run tmp OpenRefine workspace and execute shell script\n" + printf "orcli batch - run tmp OpenRefine workspace and execute shell script(s)\n" echo else - printf "orcli batch - run tmp OpenRefine workspace and execute shell script\n" + printf "orcli batch - run tmp OpenRefine workspace and execute shell script(s)\n" echo fi @@ -158,8 +158,8 @@ orcli_batch_usage() { echo # :flag.usage - echo " --interactive" - printf " provide interactive Bash shell for playground and debugging\n" + echo " --debug" + printf " do not exit on error and keep shell open\n" echo # :command.usage_args @@ -173,7 +173,6 @@ orcli_batch_usage() { # :command.usage_examples printf "Examples:\n" - printf " orcli batch --interactive\n" printf " orcli batch << EOF\n orcli import csv \"https://git.io/fj5hF\" --projectName \"duplicates\"\n orcli info \"duplicates\"\n orcli export tsv \"duplicates\"\n EOF\n" printf " orcli batch --memory \"2000M\" --port \"3334\" << EOF\n orcli import csv \"https://git.io/fj5hF\" --projectName \"duplicates\" &\n orcli import csv \"https://git.io/fj5hF\" --projectName \"copy\" &\n wait\n echo \"finished import\"\n orcli export csv \"duplicates\" --output duplicates.csv &\n orcli export tsv \"duplicates\" --output duplicates.tsv &\n wait\n wc duplicates*\n EOF\n" printf " orcli batch \"file1.sh\" \"file2.sh\" - << EOF\n echo \"finished in \$SECONDS seconds\"\n EOF\n" @@ -704,7 +703,7 @@ send_completions() { echo $' ;;' echo $'' echo $' \'batch\'*)' - echo $' while read -r; do COMPREPLY+=( "$REPLY" ); done < <( compgen -W "$(_orcli_completions_filter "--help --interactive --memory --port -h")" -- "$cur" )' + echo $' while read -r; do COMPREPLY+=( "$REPLY" ); done < <( compgen -W "$(_orcli_completions_filter "--debug --help --memory --port -h")" -- "$cur" )' echo $' ;;' echo $'' echo $' \'list\'*)' @@ -742,14 +741,6 @@ orcli_batch_command() { # src/batch_command.sh # shellcheck shell=bash disable=SC2154 source=/dev/null - # check if stdin is present if selected - if ! [[ ${args[--interactive]} ]]; then - if [[ ${args[file]} == '-' ]] || [[ ${args[file]} == '"-"' ]] && [ -t 0 ]; then - orcli_batch_usage - exit 1 - fi - fi - # catch args, convert the space delimited string to an array files=() eval "files=(${args[file]})" @@ -794,19 +785,32 @@ orcli_batch_command() { log "started OpenRefine" "port: ${args[--port]}" "memory: ${args[--memory]}" "tmpdir: ${tmpdir}" "pid: ${openrefine_pid}" fi - # execute shell script + # execute script(s) in subshell export orcli tmpdir OPENREFINE_URL openrefine_pid - if [[ ${args[--interactive]} ]]; then + # case 1: interactive mode if stdin is selected but not present + if [[ ${args[file]} == '-' || ${args[file]} == '"-"' ]]; then + if ! read -u 0 -t 0; then + bash --rcfile <( + cat ~/.bashrc + interactive + ) -i < /dev/tty + exit + fi + fi + # case 2: execute scripts and keep shell running + if [[ ${args[--debug]} ]]; then bash --rcfile <( cat ~/.bashrc + for i in "${!files[@]}"; do log "execute script ${files[$i]}"; awk 1 "${files[$i]}"; done interactive - if ! [[ ${args[file]} == '-' || ${args[file]} == '"-"' ]]; then - awk 1 "${files[@]}" - fi - ) -i - else - bash -e <(awk 1 "${files[@]}") + ) -i < /dev/tty + exit fi + # case 3: execute scripts + for i in "${!files[@]}"; do + log "execute script ${files[$i]}" + bash -e <(awk 1 "${files[$i]}") + done } @@ -819,9 +823,11 @@ orcli_import_csv_command() { init_import # check if stdin is present if selected - if [[ ${args[file]} == '-' ]] || [[ ${args[file]} == '"-"' ]] && [ -t 0 ]; then - orcli_import_csv_usage - exit 1 + if [[ ${args[file]} == '-' ]] || [[ ${args[file]} == '"-"' ]]; then + if ! read -u 0 -t 0; then + orcli_import_csv_usage + exit 1 + fi fi # assemble specific post data (some options require json format) @@ -1122,10 +1128,10 @@ orcli_batch_parse_requirements() { ;; # :flag.case - --interactive ) + --debug ) # :flag.case_no_arg - args[--interactive]=1 + args[--debug]=1 shift ;; diff --git a/src/bashly.yml b/src/bashly.yml index 357cecd..8f30e15 100644 --- a/src/bashly.yml +++ b/src/bashly.yml @@ -37,7 +37,7 @@ commands: Usage: eval "\$(orcli completions)" - name: batch - help: run tmp OpenRefine workspace and execute shell script + help: run tmp OpenRefine workspace and execute shell script(s) args: - name: file help: Path to one or more files. When FILE is -, read standard input. @@ -52,10 +52,9 @@ commands: help: PORT on which OpenRefine should listen arg: port default: "3333" - - long: --interactive - help: provide interactive Bash shell for playground and debugging + - long: --debug + help: do not exit on error and keep shell open examples: - - orcli batch --interactive - |- orcli batch << EOF orcli import csv "https://git.io/fj5hF" --projectName "duplicates" diff --git a/src/batch_command.sh b/src/batch_command.sh index e966f14..7be5651 100644 --- a/src/batch_command.sh +++ b/src/batch_command.sh @@ -1,13 +1,5 @@ # shellcheck shell=bash disable=SC2154 source=/dev/null -# check if stdin is present if selected -if ! [[ ${args[--interactive]} ]]; then - if [[ ${args[file]} == '-' ]] || [[ ${args[file]} == '"-"' ]] && [ -t 0 ]; then - orcli_batch_usage - exit 1 - fi -fi - # catch args, convert the space delimited string to an array files=() eval "files=(${args[file]})" @@ -52,16 +44,29 @@ else log "started OpenRefine" "port: ${args[--port]}" "memory: ${args[--memory]}" "tmpdir: ${tmpdir}" "pid: ${openrefine_pid}" fi -# execute shell script +# execute script(s) in subshell export orcli tmpdir OPENREFINE_URL openrefine_pid -if [[ ${args[--interactive]} ]]; then +# case 1: interactive mode if stdin is selected but not present +if [[ ${args[file]} == '-' || ${args[file]} == '"-"' ]]; then + if ! read -u 0 -t 0; then + bash --rcfile <( + cat ~/.bashrc + interactive + ) -i < /dev/tty + exit + fi +fi +# case 2: execute scripts and keep shell running +if [[ ${args[--debug]} ]]; then bash --rcfile <( cat ~/.bashrc + for i in "${!files[@]}"; do log "execute script ${files[$i]}"; awk 1 "${files[$i]}"; done interactive - if ! [[ ${args[file]} == '-' || ${args[file]} == '"-"' ]]; then - awk 1 "${files[@]}" - fi - ) -i -else - bash -e <(awk 1 "${files[@]}") + ) -i < /dev/tty + exit fi +# case 3: execute scripts +for i in "${!files[@]}"; do + log "execute script ${files[$i]}" + bash -e <(awk 1 "${files[$i]}") +done diff --git a/src/import_csv_command.sh b/src/import_csv_command.sh index 53fbc4a..a2bf97f 100644 --- a/src/import_csv_command.sh +++ b/src/import_csv_command.sh @@ -4,9 +4,11 @@ init_import # check if stdin is present if selected -if [[ ${args[file]} == '-' ]] || [[ ${args[file]} == '"-"' ]] && [ -t 0 ]; then - orcli_import_csv_usage - exit 1 +if [[ ${args[file]} == '-' ]] || [[ ${args[file]} == '"-"' ]]; then + if ! read -u 0 -t 0; then + orcli_import_csv_usage + exit 1 + fi fi # assemble specific post data (some options require json format) diff --git a/src/lib/send_completions.sh b/src/lib/send_completions.sh index 32485a5..eb72a5a 100644 --- a/src/lib/send_completions.sh +++ b/src/lib/send_completions.sh @@ -51,7 +51,7 @@ send_completions() { echo $' ;;' echo $'' echo $' \'batch\'*)' - echo $' while read -r; do COMPREPLY+=( "$REPLY" ); done < <( compgen -W "$(_orcli_completions_filter "--help --interactive --memory --port -h")" -- "$cur" )' + echo $' while read -r; do COMPREPLY+=( "$REPLY" ); done < <( compgen -W "$(_orcli_completions_filter "--debug --help --memory --port -h")" -- "$cur" )' echo $' ;;' echo $'' echo $' \'list\'*)'