#!/bin/bash
# shell - Shell script support
set -e
######
# Settings
sys_shell_config_init() {
lib_setting_vars shell_is_running shell_is_interactive
}
sys_shell_config_check() {
shell_is_running=false
shell_is_interactive=false
}
######
# Internal functions
terminal_is_interactive() {
case "$-" in
(*i*) true ;;
(*) false ;;
esac
}
shell_readline() {
local path=${PWD/$HOME/\~}
read -p "$(timestamp) $path $script_name> " -e line
}
shell_eval() {
local result=0
eval "$@" || result=$?
if [ $result -ne 0 ]; then
app_echo "shell command failed: $result"
shell_is_running=$shell_is_interactive
fi
}
shell_native() {
local -a shell_line_args=( "$@" )
shell_line_args[0]=${1#!}
shell_eval "${shell_line_args[@]}"
}
shell_builtin() {
case "$1" in
(!*) shell_native "$@"; return 0 ;;
(*=*) ;;
([[]) ;;
(history|cd|ls|mv|cp|mkdir|rm|rmdir|xargs) ;;
(test|echo|pushd|popd|sed|grep|find) ;;
(declare|typeset|set|unset|alias|unalias) ;;
(read|readarray) ;;
(error|warn|info|app_echo) ;;
(*) return 1
esac
shell_eval "$@"
true
}
shell_app_builtin() {
case "$1" in
q|quit|x|exit) shell_is_running=false; return 0 ;;
load) lib_load "$2" ;;
version) app_version; true ;;
restart) exec $0; exit ;;
*) return 1 ;;
esac
}
shell_dispatch() {
local result=0
eval script_cmd_dispatch "$@" || result=$?
if [ $result -ne 0 ]; then
app_echo "command failed: $result"
shell_is_running=$shell_is_interactive
fi
}
######
# Public interface
shell_run_core() {
info "shell $*: starting..."
local line buffered
while $shell_is_running && shell_readline; do
[ "$line" ] || continue
if [ "${line%\\}" != "$line" ]; then
buffered="$buffered${line%\\}"
continue
elif [ "$buffered" ]; then
line="$buffered$line"
buffered=""
fi
history -s "$line"
local cmd="${line%%#*}"
[ "$cmd" ] || continue
! shell_builtin $line || continue
! shell_app_builtin $line || continue
! shell_dispatch $line || continue
# halt if the shell is not interactive
$shell_is_interactive
local -a shell_line_args=( $line )
echo "error: $line_args: command not found"
done
info "shell $*: ... done!"
}
shell_run_file() {
$shell_is_running || return
info "$1: script executing..."
local args=( "$@" )
shell_run_core "$@" <$1
info "$1: ... done"
}
shell_run() {
! $shell_is_running || error "shell: recursion is not supported!"
shell_is_running=true
file_is_terminal stdin && app_version
if [ "$*" ]; then
shell_is_interactive=false
shell_run_file "$@"
else
shell_is_interactive=true
shell_run_core
fi
shell_is_running=false
}
shell_help() {
cat <<EOF
${script[*]} reads commands from standard input
Standard input can be either an interactive terminal or a pipe.
If input comes from a terminal, a prompt will be displayed.
EOF
}
Generated on Tue Apr 25 21:21:19 PDT 2017 by mcsh i7 v0.18.0.