diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 33276b71..5328cc78 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -2,6 +2,15 @@ This page summarizes a couple of rules to keep in mind when developing features or making changes in Bash-it. +## Debugging and Logging + +While developing feature or making changes in general, you can log error/warning/debug +using `_log_error` `_log_warning` and `_log_debug`. This will help you solve problems quicker +and also propagate important notes to other users of Bash-it. +You can see the logs by using `bash-it doctor` command to reload and see the logs. +Alternatively, you can set `BASH_IT_LOG_LEVEL` to `BASH_IT_LOG_LEVEL_ERROR`, `BASH_IT_LOG_LEVEL_WARNING` or `BASH_IT_LOG_LEVEL_ALL`. + + ## Load Order ### General Load Order diff --git a/README.md b/README.md index a696894e..26ac5cb7 100644 --- a/README.md +++ b/README.md @@ -417,6 +417,20 @@ Unset `BASH_IT_LEGACY_PASS` to have Bash-it **return to default behavior**: * `unset BASH_IT_LEGACY_PASS` +### Debugging + +If you encounter problems with any part of Bash-it, run the following command: +```bash +bash-it doctor +``` +This will reload your bash profile and print out logs of various parts in Bash-it. +Note that this command at default will print all logs, including debug logs. +You can call it like this: +```bash +bash-it doctor [errors/warnings/all] +``` +In order to get wanted verbosity. + ### Proxy Support If you are working in a corporate environment where you have to go through a proxy server for internet access, diff --git a/completion/available/bash-it.completion.bash b/completion/available/bash-it.completion.bash index 71ec8418..c13e8623 100644 --- a/completion/available/bash-it.completion.bash +++ b/completion/available/bash-it.completion.bash @@ -65,7 +65,7 @@ _bash-it-comp() prev="${COMP_WORDS[COMP_CWORD-1]}" chose_opt="${COMP_WORDS[1]}" file_type="${COMP_WORDS[2]}" - opts="disable enable help migrate reload search show update version" + opts="disable enable help migrate reload doctor search show update version" case "${chose_opt}" in show) local show_args="aliases completions plugins" @@ -82,6 +82,11 @@ _bash-it-comp() return 0 fi ;; + doctor) + local doctor_args="errors warnings all" + COMPREPLY=( $(compgen -W "${doctor_args}" -- ${cur}) ) + return 0 + ;; migrate | reload | search | update | version) return 0 ;; diff --git a/lib/appearance.bash b/lib/appearance.bash index 6d0ef2ff..d684332f 100644 --- a/lib/appearance.bash +++ b/lib/appearance.bash @@ -1,5 +1,15 @@ #!/usr/bin/env bash +function _has_colors() +{ + # Check that stdout is a terminal + test -t 1 || return 1 + + ncolors=$(tput colors) + test -n "$ncolors" && test "$ncolors" -ge 8 || return 1 + return 0 +} + # colored ls export LSCOLORS='Gxfxcxdxdxegedabagacad' diff --git a/lib/helpers.bash b/lib/helpers.bash index f3bd2e0b..2d05c919 100644 --- a/lib/helpers.bash +++ b/lib/helpers.bash @@ -43,7 +43,7 @@ alias reload_plugins="$(_make_reload_alias plugin plugins)" bash-it () { about 'Bash-it help and maintenance' - param '1: verb [one of: help | show | enable | disable | migrate | update | search | version | reload ] ' + param '1: verb [one of: help | show | enable | disable | migrate | update | search | version | reload | doctor ] ' param '2: component type [one of: alias(es) | completion(s) | plugin(s) ] or search term(s)' param '3: specific component [optional]' example '$ bash-it show plugins' @@ -55,6 +55,7 @@ bash-it () example '$ bash-it search [-|@]term1 [-|@]term2 ... [ -e/--enable ] [ -d/--disable ] [ -r/--refresh ] [ -c/--no-color ]' example '$ bash-it version' example '$ bash-it reload' + example '$ bash-it doctor errors|warnings|all' typeset verb=${1:-} shift typeset component=${1:-} @@ -70,6 +71,8 @@ bash-it () func=_disable-$component;; help) func=_help-$component;; + doctor) + func=_bash-it-doctor-$component;; search) _bash-it-search $component "$@" return;; @@ -263,6 +266,44 @@ _bash-it-version() { cd - &> /dev/null || return } +_bash-it-doctor() { + _about 'reloads a profile file with a BASH_IT_LOG_LEVEL set' + _param '1: BASH_IT_LOG_LEVEL argument: "errors" "warnings" "all"' + _group 'lib' + + BASH_IT_LOG_LEVEL=$1 + _bash-it-reload + unset BASH_IT_LOG_LEVEL +} + +_bash-it-doctor-all() { + _about 'reloads a profile file with error, warning and debug logs' + _group 'lib' + + _bash-it-doctor $BASH_IT_LOG_LEVEL_ALL +} + +_bash-it-doctor-warnings() { + _about 'reloads a profile file with error and warning logs' + _group 'lib' + + _bash-it-doctor $BASH_IT_LOG_LEVEL_WARNING +} + +_bash-it-doctor-errors() { + _about 'reloads a profile file with error logs' + _group 'lib' + + _bash-it-doctor $BASH_IT_LOG_LEVEL_ERROR +} + +_bash-it-doctor-() { + _about 'default bash-it doctor behavior, behaves like bash-it doctor all' + _group 'lib' + + _bash-it-doctor-all +} + _bash-it-reload() { _about 'reloads a profile file' _group 'lib' diff --git a/lib/log.bash b/lib/log.bash new file mode 100644 index 00000000..8f954359 --- /dev/null +++ b/lib/log.bash @@ -0,0 +1,48 @@ +#!/usr/bin/env bash + +export BASH_IT_LOG_LEVEL_ERROR=1 +export BASH_IT_LOG_LEVEL_WARNING=2 +export BASH_IT_LOG_LEVEL_ALL=3 + +function _log_general() +{ + _about 'Internal function used for logging' + _param '1: color of the message' + _param '2: message to log' + _group 'log' + + _has_colors && echo -e "$1$2${echo_normal}" || echo -e "$2" +} + +function _log_debug() +{ + _about 'log a debug message by echoing to the screen. needs BASH_IT_LOG_LEVEL >= BASH_IT_LOG_LEVEL_ALL' + _param '1: message to log' + _example '$ _log_debug "Loading plugin git..."' + _group 'log' + + [[ "$BASH_IT_LOG_LEVEL" -ge $BASH_IT_LOG_LEVEL_ALL ]] || return + _log_general "${echo_green}" "DEBUG: $1" +} + +function _log_warning() +{ + _about 'log a message by echoing to the screen. needs BASH_IT_LOG_LEVEL >= BASH_IT_LOG_LEVEL_WARNING' + _param '1: message to log' + _example '$ _log_warning "git binary not found, disabling git plugin..."' + _group 'log' + + [[ "$BASH_IT_LOG_LEVEL" -ge $BASH_IT_LOG_LEVEL_WARNING ]] || return + _log_general "${echo_yellow}" " WARN: $1" +} + +function _log_error() +{ + _about 'log a message by echoing to the screen. needs BASH_IT_LOG_LEVEL >= BASH_IT_LOG_LEVEL_ERROR' + _param '1: message to log' + _example '$ _log_error "Failed to load git plugin..."' + _group 'log' + + [[ "$BASH_IT_LOG_LEVEL" -ge $BASH_IT_LOG_LEVEL_ERROR ]] || return + _log_general "${echo_red}" "ERROR: $1" +} diff --git a/test/completion/bash-it.completion.bats b/test/completion/bash-it.completion.bats index 87c697e4..e453ae43 100644 --- a/test/completion/bash-it.completion.bats +++ b/test/completion/bash-it.completion.bats @@ -43,6 +43,11 @@ function __check_completion () { echo "${COMPREPLY[@]}" } +@test "completion bash-it: doctor - show options" { + run __check_completion 'bash-it doctor ' + assert_line -n 0 "errors warnings all" +} + @test "completion bash-it: help - show options" { run __check_completion 'bash-it help ' assert_line -n 0 "aliases completions migrate plugins update" @@ -70,32 +75,32 @@ function __check_completion () { @test "completion bash-it: show options" { run __check_completion 'bash-it ' - assert_line -n 0 "disable enable help migrate reload search show update version" + assert_line -n 0 "disable enable help migrate reload doctor search show update version" } @test "completion bash-it: bash-ti - show options" { run __check_completion 'bash-ti ' - assert_line -n 0 "disable enable help migrate reload search show update version" + assert_line -n 0 "disable enable help migrate reload doctor search show update version" } @test "completion bash-it: shit - show options" { run __check_completion 'shit ' - assert_line -n 0 "disable enable help migrate reload search show update version" + assert_line -n 0 "disable enable help migrate reload doctor search show update version" } @test "completion bash-it: bashit - show options" { run __check_completion 'bashit ' - assert_line -n 0 "disable enable help migrate reload search show update version" + assert_line -n 0 "disable enable help migrate reload doctor search show update version" } @test "completion bash-it: batshit - show options" { run __check_completion 'batshit ' - assert_line -n 0 "disable enable help migrate reload search show update version" + assert_line -n 0 "disable enable help migrate reload doctor search show update version" } @test "completion bash-it: bash_it - show options" { run __check_completion 'bash_it ' - assert_line -n 0 "disable enable help migrate reload search show update version" + assert_line -n 0 "disable enable help migrate reload doctor search show update version" } @test "completion bash-it: show - show options" { diff --git a/test/lib/log.bats b/test/lib/log.bats new file mode 100644 index 00000000..da31a9b5 --- /dev/null +++ b/test/lib/log.bats @@ -0,0 +1,79 @@ +#!/usr/bin/env bats + +load ../test_helper +load ../../lib/composure +load ../../lib/appearance +load ../../plugins/available/base.plugin + +cite _about _param _example _group _author _version +load ../../lib/log + +@test "lib log: basic debug logging with BASH_IT_LOG_LEVEL_ALL" { + BASH_IT_LOG_LEVEL=$BASH_IT_LOG_LEVEL_ALL + run _log_debug "test test test" + assert_output "DEBUG: test test test" +} + +@test "lib log: basic warning logging with BASH_IT_LOG_LEVEL_ALL" { + BASH_IT_LOG_LEVEL=$BASH_IT_LOG_LEVEL_ALL + run _log_warning "test test test" + assert_output " WARN: test test test" +} + +@test "lib log: basic error logging with BASH_IT_LOG_LEVEL_ALL" { + BASH_IT_LOG_LEVEL=$BASH_IT_LOG_LEVEL_ALL + run _log_error "test test test" + assert_output "ERROR: test test test" +} + +@test "lib log: basic debug logging with BASH_IT_LOG_LEVEL_WARNING" { + BASH_IT_LOG_LEVEL=$BASH_IT_LOG_LEVEL_WARNING + run _log_debug "test test test" + refute_output +} + +@test "lib log: basic warning logging with BASH_IT_LOG_LEVEL_WARNING" { + BASH_IT_LOG_LEVEL=$BASH_IT_LOG_LEVEL_WARNING + run _log_warning "test test test" + assert_output " WARN: test test test" +} + +@test "lib log: basic error logging with BASH_IT_LOG_LEVEL_WARNING" { + BASH_IT_LOG_LEVEL=$BASH_IT_LOG_LEVEL_WARNING + run _log_error "test test test" + assert_output "ERROR: test test test" +} + + +@test "lib log: basic debug logging with BASH_IT_LOG_LEVEL_ERROR" { + BASH_IT_LOG_LEVEL=$BASH_IT_LOG_LEVEL_ERROR + run _log_debug "test test test" + refute_output +} + +@test "lib log: basic warning logging with BASH_IT_LOG_LEVEL_ERROR" { + BASH_IT_LOG_LEVEL=$BASH_IT_LOG_LEVEL_ERROR + run _log_warning "test test test" + refute_output +} + +@test "lib log: basic error logging with BASH_IT_LOG_LEVEL_ERROR" { + BASH_IT_LOG_LEVEL=$BASH_IT_LOG_LEVEL_ERROR + run _log_error "test test test" + assert_output "ERROR: test test test" +} + +@test "lib log: basic debug silent logging" { + run _log_debug "test test test" + refute_output +} + +@test "lib log: basic warning silent logging" { + run _log_warning "test test test" + refute_output +} + +@test "lib log: basic error silent logging" { + run _log_error "test test test" + refute_output +}