From 9a113c361f0705b7da1fa24a93a73bb58e9978f4 Mon Sep 17 00:00:00 2001 From: Ryan Caloras Date: Sat, 29 Nov 2014 23:32:13 -0500 Subject: [PATCH] Migrated to using traps instead PROMPT_COMMAND - Created preexec.sh based off http://www.twistedmatrix.com/users/glyph/preexec.bash.txt. Eventually pull this into its own repo. Maybe use bpkg - Redirected errors and stdout to log.txt --- MANIFEST.in | 3 +- bashhub/shell/bashhub.sh | 40 ++++----- bashhub/shell/bashhub.zsh | 16 +++- bashhub/shell/{ => deps}/lib-bashhub.sh | 7 ++ bashhub/shell/deps/preexec.sh | 106 ++++++++++++++++++++++++ install-bashhub.sh | 7 +- 6 files changed, 150 insertions(+), 29 deletions(-) rename bashhub/shell/{ => deps}/lib-bashhub.sh (93%) create mode 100644 bashhub/shell/deps/preexec.sh diff --git a/MANIFEST.in b/MANIFEST.in index a418451..53ef4bf 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,4 +1,5 @@ include README.md -include bashhub/shell/*.sh include bashhub/shell/*.zsh +include bashhub/shell/*.sh +include bashhub/shell/deps/*.sh include bashhub/model/* diff --git a/bashhub/shell/bashhub.sh b/bashhub/shell/bashhub.sh index adfe3ea..020109d 100644 --- a/bashhub/shell/bashhub.sh +++ b/bashhub/shell/bashhub.sh @@ -1,35 +1,31 @@ -source ~/.bashhub/.config -source ~/.bashhub/lib-bashhub.sh +# +# bashhub.sh +# Main file that is sourced onto our path for Bash. +# export BH_HOME_DIRECTORY="$HOME/.bashhub/" export BH_EXEC_DIRECTORY="$HOME/.bashhub/env/bin" -# Alias to bind Ctrl + B -bind '"\C-b":"\C-u\C-kbh -i\n"' -BH_GET_LAST_COMMAND() { - # GRAB LAST OF COMMAND - local HISTORY_LINE=$(history 1) - local TRIMMED_COMMAND=`BH_TRIM_WHITESPACE $HISTORY_LINE` - local NO_LINE_NUMBER=`echo "$TRIMMED_COMMAND" | cut -d " " -f2-` - BH_TRIM_WHITESPACE $NO_LINE_NUMBER -} +BH_DEPS_DIRECTORY=$BH_HOME_DIRECTORY/deps -BH_ON_PROMPT_COMMAND() { +# Import our dependencies +if [[ -f $BH_DEPS_DIRECTORY/lib-bashhub.sh ]]; then + source $BH_DEPS_DIRECTORY/lib-bashhub.sh +fi - BH_PREV_COMMAND="$BH_COMMAND" - BH_COMMAND=$(BH_GET_LAST_COMMAND) +# Import prexec +if [[ -f $BH_DEPS_DIRECTORY/preexec.sh ]]; then + source $BH_DEPS_DIRECTORY/preexec.sh + preexec_install +fi - # Check to make sure we have a new command - if [[ "$BH_COMMAND" = "$BH_PREV_COMMAND" ]]; then - return 0 - fi; +# Alias to bind Ctrl + B +bind '"\C-b":"\C-u\C-kbh -i\n"' - BH_PREEXEC "$BH_COMMAND" +preexec() { + BH_PREEXEC "$1" &> ~/.bashhub/log.txt } -# Hook into Bash's PROMPT_COMMAND. -PROMPT_COMMAND="BH_ON_PROMPT_COMMAND; $PROMPT_COMMAND" - bh() { $BH_EXEC_DIRECTORY/bh "$@" diff --git a/bashhub/shell/bashhub.zsh b/bashhub/shell/bashhub.zsh index 79f02b7..1c8a617 100644 --- a/bashhub/shell/bashhub.zsh +++ b/bashhub/shell/bashhub.zsh @@ -1,11 +1,21 @@ -source ~/.bashhub/.config -source ~/.bashhub/lib-bashhub.sh +# +# bashhub.zsh +# Main file that is sourced onto our path for Zsh. +# export BH_HOME_DIRECTORY="$HOME/.bashhub/" export BH_EXEC_DIRECTORY="$HOME/.bashhub/env/bin" +BH_DEPS_DIRECTORY=$BH_HOME_DIRECTORY/deps + +# Import our dependencies +if [[ -f $BH_DEPS_DIRECTORY/lib-bashhub.sh ]]; then + source $BH_DEPS_DIRECTORY/lib-bashhub.sh +fi + + function bh_preexec() { - (BH_PREEXEC $1) + BH_PREEXEC $1 &> ~/.bashhub/log.txt } function bh_precmd() { diff --git a/bashhub/shell/lib-bashhub.sh b/bashhub/shell/deps/lib-bashhub.sh similarity index 93% rename from bashhub/shell/lib-bashhub.sh rename to bashhub/shell/deps/lib-bashhub.sh index 253012d..8987058 100644 --- a/bashhub/shell/lib-bashhub.sh +++ b/bashhub/shell/deps/lib-bashhub.sh @@ -6,6 +6,13 @@ export PATH=$PATH:"$HOME/.bashhub/bin" +BH_INCLUDE() { + [[ -f "$1" ]] && source "$1" +} + +# Include our user configuration +BH_INCLUDE ~/.bashhub/.config + # # Prepare and send our command to be processed. # diff --git a/bashhub/shell/deps/preexec.sh b/bashhub/shell/deps/preexec.sh new file mode 100644 index 0000000..e9be22a --- /dev/null +++ b/bashhub/shell/deps/preexec.sh @@ -0,0 +1,106 @@ +#!/bin/bash + +# preexec.bash -- Bash support for ZSH-like 'preexec' and 'precmd' functions. + +# The 'preexec' function is executed before each interactive command is +# executed, with the interactive command as its argument. The 'precmd' +# function is executed before each prompt is displayed. + +# To use, in order: + +# 1. source this file +# 2. define 'preexec' and/or 'precmd' functions (AFTER sourcing this file), +# 3. as near as possible to the end of your shell setup, run 'preexec_install' +# to kick everything off. + +# Note: this module requires 2 bash features which you must not otherwise be +# using: the "DEBUG" trap, and the "PROMPT_COMMAND" variable. preexec_install +# will override these and if you override one or the other this _will_ break. + +# This variable describes whether we are currently in "interactive mode"; +# i.e. whether this shell has just executed a prompt and is waiting for user +# input. It documents whether the current command invoked by the trace hook is +# run interactively by the user; it's set immediately after the prompt hook, +# and unset as soon as the trace hook is run. +preexec_interactive_mode="" + +# Default do-nothing implementation of preexec. +preexec() { + : +} + +# Default do-nothing implementation of precmd. +precmd() { + : +} + +# This function is installed as the PROMPT_COMMAND; it is invoked before each +# interactive prompt display. It sets a variable to indicate that the prompt +# was just displayed, to allow the DEBUG trap, below, to know that the next +# command is likely interactive. +preexec_invoke_cmd() { + last_hist_ent="$(history 1)"; + precmd; + preexec_interactive_mode="on"; +} + +# This function is installed as the DEBUG trap. It is invoked before each +# interactive prompt display. Its purpose is to inspect the current +# environment to attempt to detect if the current command is being invoked +# interactively, and invoke 'preexec' if so. +preexec_invoke_exec() { + if [[ -n "$COMP_LINE" ]] + then + # We're in the middle of a completer. This obviously can't be + # an interactively issued command. + return + fi + if [[ -z "$preexec_interactive_mode" ]] + then + # We're doing something related to displaying the prompt. Let the + # prompt set the title instead of me. + return + else + # If we're in a subshell, then the prompt won't be re-displayed to put + # us back into interactive mode, so let's not set the variable back. + # In other words, if you have a subshell like + # (sleep 1; sleep 2) + # You want to see the 'sleep 2' as a set_command_title as well. + if [[ 0 -eq "$BASH_SUBSHELL" ]] + then + preexec_interactive_mode="" + fi + fi + + if [[ "preexec_invoke_cmd" == "$BASH_COMMAND" ]] + then + # Sadly, there's no cleaner way to detect two prompts being displayed + # one after another. This makes it important that PROMPT_COMMAND + # remain set _exactly_ as below in preexec_install. Let's switch back + # out of interactive mode and not trace any of the commands run in + # precmd. + + # Given their buggy interaction between BASH_COMMAND and debug traps, + # versions of bash prior to 3.1 can't detect this at all. + preexec_interactive_mode="" + return + fi + + local hist_ent="$(history 1)"; + local this_command="$(echo "$hist_ent" | sed -e "s/^[ ]*[0-9]*[ ]*//g")"; + + # If none of the previous checks have returned out of this function, then + # the command is in fact interactive and we should invoke the user's + # preexec hook with the running command as an argument. + if [ -n "$this_command" ]; then + preexec "$this_command"; + fi +} + +# Execute this to set up preexec and precmd execution. +preexec_install() { + + # Finally, install the actual traps. + PROMPT_COMMAND="${PROMPT_COMMAND} preexec_invoke_cmd"; + trap 'preexec_invoke_exec' DEBUG; +} diff --git a/install-bashhub.sh b/install-bashhub.sh index f2964ba..646199d 100755 --- a/install-bashhub.sh +++ b/install-bashhub.sh @@ -91,7 +91,7 @@ setup_bashhub_files () { # Have to have this. Error out otherwise. if [ -z "$bashprofile" ]; then - die "No bashfile (e.g. .profile, .bashrc, ect) could be found" 1 + die "No bashfile (e.g. .profile, .bashrc, etc) could be found" 1 fi mkdir ~/.bashhub @@ -103,9 +103,10 @@ setup_bashhub_files () { tar -xvf client.tar.gz cd bashhub-client* - # Copy over our sh files + # Copy over our sh files. cp bashhub/shell/bashhub.sh ~/.bashhub/ - cp bashhub/shell/lib-bashhub.sh ~/.bashhub/ + # Copy over our dependencies. + cp -r bashhub/shell/deps ~/.bashhub/ # Add our file to our bashprofile if it doesn't exist yet if grep -q "source ~/.bashhub/bashhub.sh" $bashprofile