diff --git a/.travis.yml b/.travis.yml index 34c38fe7..b3fa2728 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,6 @@ sudo: false script: test/run language: c +os: + - linux + - osx diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b9bd7d91..9c365a75 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -23,6 +23,25 @@ When contributing a new feature, a bug fix, a new theme, or any other change to * Internal functions that aren't to be used by the end user should start with an underscore, e.g. `_my-new-internal-function`. * Use the provided meta functions to document your code, e.g. `about-plugin`, `about`, `group`, `param`, `example`. This will make it easier for other people to use your new functionality. Take a look at the existing code for an example (e.g. [the base plugin](plugins/available/base.plugin.bash)). * When adding files, please use the existing file naming conventions, e.g. plugin files need to end in `.plugin.bash`. This is important for the installation functionality. +* When using the `$BASH_IT` variable, please always enclose it in double quotes to ensure that the code also works when Bash-it is installed in a directory that contains spaces in its name: `for f in "${BASH_IT}/plugins/available"/*.bash ; do echo "$f" ; done` + +## Unit Tests + +When adding features or making changes/fixes, please run our growing unit test suite to ensure that you did not break existing functionality. The test suite does not cover all aspects of Bash-it, but please run it anyway to verify that you did not introduce any regression issues. + +Any code pushed to GitHub as part of a Pull Request will automatically trigger a continuous integration build on [Travis CI](https://travis-ci.org/Bash-it/bash-it), where the test suite is run on both Linux and macOS. The Pull Request will then show the result of the Travis build, indicating whether all tests ran fine, or whether there were issues. Please pay attention to this, Pull Requests with build issues will not be merged. + +Adding new functionality or changing existing functionality is a good opportunity to increase Bash-it's test coverage. When you're changing the Bash-it codebase, please consider adding some unit tests that cover the new or changed functionality. Ideally, when fixing a bug, a matching unit test that verifies that the bug is no longer present, is added at the same time. + +To run the test suite, simply execute the following in the directory where you cloned Bash-it: + +```bash +test/run +``` + +This command will clone the [Bats Test Framework](https://github.com/sstephenson/bats) to a local directory and then run the test suite found in the [test](test) folder. The test script will execute each test in turn, and will print a status for each test case. + +When adding new test cases, please take a look at the existing test cases for examples. ## Features @@ -30,5 +49,5 @@ When contributing a new feature, a bug fix, a new theme, or any other change to ## Themes -* When adding a new theme, please include a screenshot and a short description about what makes this theme unique in the Pull Request. +* When adding a new theme, please include a screenshot and a short description about what makes this theme unique in the Pull Request's description field. Please do not add theme screenshots to the repo itself, as they will add unnecessary bloat to the repo. The project's Wiki has a _Themes_ page where you can add a screenshot if you want. * Ideally, each theme's folder should contain a `README.md` file describing the theme and its configuration options. diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md new file mode 100644 index 00000000..d9c0abf6 --- /dev/null +++ b/DEVELOPMENT.md @@ -0,0 +1,43 @@ +# Bash-it Development + +This page summarizes a couple of rules to keep in mind when developing features or making changes in Bash-it. + +## Load Order + +### General Load Order + +The main `bash_it.sh` script loads the frameworks individual components in the following order: + +* `lib/composure.bash` +* Files in `lib` with the exception of `appearance.bash` - this means that `composure.bash` is loaded again here (possible improvement?) +* Enabled `aliases` +* Enabled `plugins` +* Enabled `completions` +* `themes/colors.theme.bash` +* `themes/base.theme.bash` +* `lib/appearance.bash`, which loads the selected theme +* Custom `aliases` +* Custom `plugins` +* Custom `completions` +* Additional custom files from either `$BASH_IT/custom` or `$BASH_IT_CUSTOM` + +This order is subject to change. + +### Individual Component Load Order + +For `aliases`, `plugins` and `completions`, the following rules are applied that influence the load order: + +* Each type has its own `enabled` directory, into which the enabled components are linked into. Enabled plugins are symlinked from `$BASH_IT/plugins/available` to `$BASH_IT/plugins/enabled` for example. +* Within each of the `enabled` directories, the files are loaded in alphabetical order. +* When enabling a component, a _load priority_ is assigned to the file. The following default priorities are used: + * Aliases: 150 + * Plugins: 250 + * Completions: 350 +* When symlinking a component into an `enabled` directory, the load priority is used as a prefix for the linked name, separated with three dashes from the name of the component. The `node.plugin.bash` would be symlinked to `250---node.plugin.bash` for example. +* Each file can override the default load priority by specifying a new value. To do this, the file needs to include a comment in the following form. This example would cause the `node.plugin.bash` (if included in that file) to be linked to `225---node.plugin.bash`: + + ```bash + # BASH_IT_LOAD_PRIORITY: 225 + ``` + +These items are subject to change. When making changes to the internal functionality, this page needs to be updated as well. diff --git a/README.md b/README.md index 6219d636..47f546da 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,12 @@ Includes autocompletion, themes, aliases, custom functions, a few stolen pieces Bash-it provides a solid framework for using, developing and maintaining shell scripts and custom commands for your daily work. If you're using the _Bourne Again Shell_ (Bash) on a regular basis and have been looking for an easy way on how to keep all of these nice little scripts and aliases under control, then Bash-it is for you! Stop polluting your `~/bin` directory and your `.bashrc` file, fork/clone Bash-it and start hacking away. +## Contributing + +Please take a look at the [Contribution Guidelines](CONTRIBUTING.md) before reporting a bug or providing a new feature. + +The [Development Guidelines](DEVELOPMENT.md) have more information on some of the internal workings of Bash-it, please feel free to read through this page if you're interested in how Bash-it loads its components. + ## Install 1. Check out a clone of this repo to a location of your choice, such as: `git clone --depth=1 https://github.com/Bash-it/bash-it.git ~/.bash_it` @@ -49,17 +55,25 @@ Have a look at our [bash-it-docker respository](https://github.com/Bash-it/bash- ## Update -To update Bash-it, simply run: +To update Bash-it to the latest version, simply run: -``` +```bash bash-it update ``` that's all. +If you are using an older version of Bash-it, it's possible that some functionality has changed, or that the internal structure of how Bash-it organizes its functionality has been updated. For these cases, we provide a `migrate` command: + +```bash +bash-it migrate +``` + +This command will automatically migrate the Bash-it structure to the latest version. The `migrate` command is run automatically if you run the `update`, `enable` or `disable` commands. + ## Help Screens -``` +```bash bash-it show aliases # shows installed and available aliases bash-it show completions # shows installed and available completions bash-it show plugins # shows installed and available plugins @@ -174,10 +188,6 @@ cd $BASH_IT This will restore your previous Bash profile. After the uninstall script finishes, remove the Bash-it directory from your machine (`rm -rf $BASH_IT`) and start a new shell. -## Contributing - -Please take a look at the [Contribution Guidelines](CONTRIBUTING.md) before reporting a bug or providing a new feature. - ## Misc ### Bash Profile Aliases diff --git a/aliases/available/general.aliases.bash b/aliases/available/general.aliases.bash index a4cf4ee2..2d232a1b 100644 --- a/aliases/available/general.aliases.bash +++ b/aliases/available/general.aliases.bash @@ -21,14 +21,13 @@ alias _="sudo" # colored grep # Need to check an existing file for a pattern that will be found to ensure # that the check works when on an OS that supports the color option -if grep --color=auto "a" $BASH_IT/*.md &> /dev/null +if grep --color=auto "a" "${BASH_IT}/"*.md &> /dev/null then alias grep='grep --color=auto' export GREP_COLOR='1;33' fi -which gshuf &> /dev/null -if [ $? -eq 0 ] +if which gshuf &> /dev/null then alias shuf=gshuf fi diff --git a/bash_it.sh b/bash_it.sh index 065069ff..43a7509b 100755 --- a/bash_it.sh +++ b/bash_it.sh @@ -34,10 +34,6 @@ source "${BASH_IT}/lib/composure.bash" # support 'plumbing' metadata cite _about _param _example _group _author _version -# Load colors first so they can be use in base theme -source "${BASH_IT}/themes/colors.theme.bash" -source "${BASH_IT}/themes/base.theme.bash" - # libraries, but skip appearance (themes) for now LIB="${BASH_IT}/lib/*.bash" APPEARANCE_LIB="${BASH_IT}/lib/appearance.bash" @@ -54,6 +50,10 @@ do _load_bash_it_files $file_type done +# Load colors first so they can be used in base theme +source "${BASH_IT}/themes/colors.theme.bash" +source "${BASH_IT}/themes/base.theme.bash" + # appearance (themes) now, after all dependencies source $APPEARANCE_LIB diff --git a/completion/available/bash-it.completion.bash b/completion/available/bash-it.completion.bash index edcad0ea..e3e37ce6 100644 --- a/completion/available/bash-it.completion.bash +++ b/completion/available/bash-it.completion.bash @@ -10,9 +10,9 @@ _bash-it-comp-list-available-not-enabled() { subdirectory="$1" - local available_things=$(for f in `ls -1 $BASH_IT/$subdirectory/available/*.bash`; + local available_things=$(for f in `ls -1 "${BASH_IT}/$subdirectory/available/"*.bash`; do - if [ ! -e $BASH_IT/$subdirectory/enabled/$(basename $f) ] + if [ ! -e "${BASH_IT}/$subdirectory/enabled/"$(basename $f) ] && [ ! -e "${BASH_IT}/$subdirectory/enabled/"*$BASH_IT_LOAD_PRIORITY_SEPARATOR$(basename $f) ] then basename $f | cut -d'.' -f1 fi @@ -25,9 +25,9 @@ _bash-it-comp-list-enabled() { subdirectory="$1" - local enabled_things=$(for f in `ls -1 $BASH_IT/$subdirectory/enabled/*.bash`; + local enabled_things=$(for f in `ls -1 "${BASH_IT}/$subdirectory/enabled/"*.bash`; do - basename $f | cut -d'.' -f1 + basename $f | cut -d'.' -f1 | sed -e "s/^[0-9]*---//g" done) COMPREPLY=( $(compgen -W "all ${enabled_things}" -- ${cur}) ) @@ -37,7 +37,7 @@ _bash-it-comp-list-available() { subdirectory="$1" - local enabled_things=$(for f in `ls -1 $BASH_IT/$subdirectory/available/*.bash`; + local enabled_things=$(for f in `ls -1 "${BASH_IT}/$subdirectory/available/"*.bash`; do basename $f | cut -d'.' -f1 done) @@ -53,7 +53,7 @@ _bash-it-comp() prev="${COMP_WORDS[COMP_CWORD-1]}" chose_opt="${COMP_WORDS[1]}" file_type="${COMP_WORDS[2]}" - opts="help show enable disable update search" + opts="help show enable disable update search migrate" case "${chose_opt}" in show) local show_args="plugins aliases completions" @@ -61,11 +61,11 @@ _bash-it-comp() return 0 ;; help) - local help_args="plugins aliases completions update" + local help_args="plugins aliases completions migrate update" COMPREPLY=( $(compgen -W "${help_args}" -- ${cur}) ) return 0 ;; - update | search) + update | search | migrate) return 0 ;; enable | disable) diff --git a/install.sh b/install.sh index 4cd7f4d9..7fa8cacf 100755 --- a/install.sh +++ b/install.sh @@ -30,16 +30,19 @@ function load_one() { # Interactively enable several things function load_some() { file_type=$1 + single_type=$(echo "$file_type" | sed -e "s/aliases$/alias/g" | sed -e "s/plugins$/plugin/g") + enable_func="_enable-$single_type" [ -d "$BASH_IT/$file_type/enabled" ] || mkdir "$BASH_IT/$file_type/enabled" for path in "$BASH_IT/${file_type}/available/"[^_]* do file_name=$(basename "$path") while true do - read -e -n 1 -p "Would you like to enable the ${file_name%%.*} $file_type? [y/N] " RESP + just_the_name="${file_name%%.*}" + read -e -n 1 -p "Would you like to enable the $just_the_name $file_type? [y/N] " RESP case $RESP in [yY]) - ln -s "../available/${file_name}" "$BASH_IT/$file_type/enabled" + $enable_func $just_the_name break ;; [nN]|"") @@ -150,6 +153,11 @@ elif [[ $silent ]] && ! [[ $no_modify_config ]]; then backup_new fi +# Load dependencies for enabling components +source "$BASH_IT/lib/composure.bash" +cite _about _param _example _group _author _version +source "$BASH_IT/lib/helpers.bash" + if [[ $interactive ]] && ! [[ $silent ]] ; then for type in "aliases" "plugins" "completion" @@ -160,11 +168,11 @@ then else echo "" echo -e "\033[0;32mEnabling sane defaults\033[0m" - load_one completion bash-it.completion.bash - load_one completion system.completion.bash - load_one plugins base.plugin.bash - load_one plugins alias-completion.plugin.bash - load_one aliases general.aliases.bash + _enable-completion bash-it + _enable-completion system + _enable-plugin base + _enable-plugin alias-completion + _enable-alias general fi echo "" diff --git a/lib/helpers.bash b/lib/helpers.bash index 1153fc6f..0184455e 100644 --- a/lib/helpers.bash +++ b/lib/helpers.bash @@ -1,3 +1,8 @@ +BASH_IT_LOAD_PRIORITY_DEFAULT_ALIAS=${BASH_IT_LOAD_PRIORITY_DEFAULT_ALIAS:-150} +BASH_IT_LOAD_PRIORITY_DEFAULT_PLUGIN=${BASH_IT_LOAD_PRIORITY_DEFAULT_PLUGIN:-250} +BASH_IT_LOAD_PRIORITY_DEFAULT_COMPLETION=${BASH_IT_LOAD_PRIORITY_DEFAULT_COMPLETION:-350} +BASH_IT_LOAD_PRIORITY_SEPARATOR="---" + # Helper function loading various enable-able files function _load_bash_it_files() { subdirectory="$1" @@ -31,13 +36,14 @@ function reload_plugins() { bash-it () { about 'Bash-it help and maintenance' - param '1: verb [one of: help | show | enable | disable | update | search ] ' + param '1: verb [one of: help | show | enable | disable | migrate | update | search ] ' 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' example '$ bash-it help aliases' example '$ bash-it enable plugin git [tmux]...' example '$ bash-it disable alias hg [tmux]...' + example '$ bash-it migrate' example '$ bash-it update' example '$ bash-it search ruby [[-]rake]... [--enable | --disable]' typeset verb=${1:-} @@ -59,6 +65,8 @@ bash-it () return;; update) func=_bash-it_update;; + migrate) + func=_bash-it-migrate;; *) reference bash-it return;; @@ -80,6 +88,9 @@ bash-it () fi if [ x"$verb" == x"enable" -o x"$verb" == x"disable" ];then + # Automatically run a migration if required + _bash-it-migrate + for arg in "$@" do $func $arg @@ -134,7 +145,12 @@ _bash-it_update() { if [[ -n "${status}" ]]; then git pull --rebase &> /dev/null if [[ $? -eq 0 ]]; then - echo "Bash-it successfully updated, enjoy!" + echo "Bash-it successfully updated." + echo "" + echo "Migrating your installation to the latest version now..." + _bash-it-migrate + echo "" + echo "All done, enjoy!" reload else echo "Error updating Bash-it, please, check if your Bash-it installation folder (${BASH_IT}) is clean." @@ -145,6 +161,36 @@ _bash-it_update() { cd - &> /dev/null } +_bash-it-migrate() { + _about 'migrates Bash-it configuration from a previous format to the current one' + _group 'lib' + + for file_type in "aliases" "plugins" "completion" + do + shopt -s nullglob + for f in "${BASH_IT}/$file_type/enabled/"*.bash + do + typeset ff=$(basename $f) + + # Only process the ones that don't use the new structure + if ! [[ $ff =~ ^[0-9]*$BASH_IT_LOAD_PRIORITY_SEPARATOR.*\.bash$ ]] ; then + # Get the type of component from the extension + typeset single_type=$(echo $ff | sed -e 's/.*\.\(.*\)\.bash/\1/g' | sed 's/aliases/alias/g') + typeset component_name=$(echo $ff | cut -d'.' -f1) + + echo "Migrating $single_type $component_name." + + disable_func="_disable-$single_type" + enable_func="_enable-$single_type" + + $disable_func $component_name + $enable_func $component_name + fi + done + shopt -u nullglob + done +} + _bash-it-describe () { _about 'summarizes available bash_it components' @@ -162,14 +208,15 @@ _bash-it-describe () typeset f typeset enabled printf "%-20s%-10s%s\n" "$column_header" 'Enabled?' 'Description' - for f in $BASH_IT/$subdirectory/available/*.bash + for f in "${BASH_IT}/$subdirectory/available/"*.bash do - if [ -e $BASH_IT/$subdirectory/enabled/$(basename $f) ]; then + # Check for both the old format without the load priority, and the extended format with the priority + if [ -e "${BASH_IT}/$subdirectory/enabled/"$(basename $f) ] || [ -e "${BASH_IT}/$subdirectory/enabled/"*$BASH_IT_LOAD_PRIORITY_SEPARATOR$(basename $f) ]; then enabled='x' else enabled=' ' fi - printf "%-20s%-10s%s\n" "$(basename $f | cut -d'.' -f1)" " [$enabled]" "$(cat $f | metafor about-$file_type)" + printf "%-20s%-10s%s\n" "$(basename $f | sed -e 's/\(.*\)\..*\.bash/\1/g')" " [$enabled]" "$(cat $f | metafor about-$file_type)" done printf '\n%s\n' "to enable $preposition $file_type, do:" printf '%s\n' "$ bash-it enable $file_type <$file_type name> [$file_type name]... -or- $ bash-it enable $file_type all" @@ -226,20 +273,27 @@ _disable-thing () if [ "$file_entity" = "all" ]; then typeset f $file_type - for f in $BASH_IT/$subdirectory/available/*.bash + for f in "${BASH_IT}/$subdirectory/available/"*.bash do plugin=$(basename $f) - if [ -e $BASH_IT/$subdirectory/enabled/$plugin ]; then - rm $BASH_IT/$subdirectory/enabled/$(basename $plugin) + if [ -e "${BASH_IT}/$subdirectory/enabled/$plugin" ]; then + rm "${BASH_IT}/$subdirectory/enabled/$(basename $plugin)" + fi + if [ -e "${BASH_IT}/$subdirectory/enabled/"*$BASH_IT_LOAD_PRIORITY_SEPARATOR$plugin ]; then + rm "${BASH_IT}/$subdirectory/enabled/"*$BASH_IT_LOAD_PRIORITY_SEPARATOR$(basename $plugin) fi done else - typeset plugin=$(command ls $BASH_IT/$subdirectory/enabled/$file_entity.*bash 2>/dev/null | head -1) + # Use a glob to search for both possible patterns + # 250---node.plugin.bash + # node.plugin.bash + # Either one will be matched by this glob + typeset plugin=$(command ls $ "${BASH_IT}/$subdirectory/enabled/"{[0-9]*$BASH_IT_LOAD_PRIORITY_SEPARATOR$file_entity.*bash,$file_entity.*bash} 2>/dev/null | head -1) if [ -z "$plugin" ]; then printf '%s\n' "sorry, $file_entity does not appear to be an enabled $file_type." return fi - rm $BASH_IT/$subdirectory/enabled/$(basename $plugin) + rm "${BASH_IT}/$subdirectory/enabled/$(basename $plugin)" fi if [ -n "$BASH_IT_AUTOMATIC_RELOAD_AFTER_CONFIG_CHANGE" ]; then @@ -256,7 +310,7 @@ _enable-plugin () _example '$ enable-plugin rvm' _group 'lib' - _enable-thing "plugins" "plugin" $1 + _enable-thing "plugins" "plugin" $1 $BASH_IT_LOAD_PRIORITY_DEFAULT_PLUGIN } _enable-alias () @@ -266,7 +320,7 @@ _enable-alias () _example '$ enable-alias git' _group 'lib' - _enable-thing "aliases" "alias" $1 + _enable-thing "aliases" "alias" $1 $BASH_IT_LOAD_PRIORITY_DEFAULT_ALIAS } _enable-completion () @@ -276,7 +330,7 @@ _enable-completion () _example '$ enable-completion git' _group 'lib' - _enable-thing "completion" "completion" $1 + _enable-thing "completion" "completion" $1 $BASH_IT_LOAD_PRIORITY_DEFAULT_COMPLETION } _enable-thing () @@ -286,11 +340,13 @@ _enable-thing () _param '1: subdirectory' _param '2: file_type' _param '3: file_entity' - _example '$ _enable-thing "plugins" "plugin" "ssh"' + _param '4: load priority' + _example '$ _enable-thing "plugins" "plugin" "ssh" "150"' subdirectory="$1" file_type="$2" file_entity="$3" + load_priority="$4" if [ -z "$file_entity" ]; then reference "enable-$file_type" @@ -299,36 +355,40 @@ _enable-thing () if [ "$file_entity" = "all" ]; then typeset f $file_type - for f in $BASH_IT/$subdirectory/available/*.bash + for f in "${BASH_IT}/$subdirectory/available/"*.bash do - plugin=$(basename $f) - if [ ! -h $BASH_IT/$subdirectory/enabled/$plugin ]; then - ln -s ../available/$plugin $BASH_IT/$subdirectory/enabled/$plugin - fi + to_enable=$(basename $f .$file_type.bash) + _enable-thing $subdirectory $file_type $to_enable $load_priority done else - typeset plugin=$(command ls $BASH_IT/$subdirectory/available/$file_entity.*bash 2>/dev/null | head -1) - if [ -z "$plugin" ]; then + typeset to_enable=$(command ls "${BASH_IT}/$subdirectory/available/"$file_entity.*bash 2>/dev/null | head -1) + if [ -z "$to_enable" ]; then printf '%s\n' "sorry, $file_entity does not appear to be an available $file_type." return fi - plugin=$(basename $plugin) - if [ -e $BASH_IT/$subdirectory/enabled/$plugin ]; then - printf '%s\n' "$file_entity is already enabled." - return + to_enable=$(basename $to_enable) + # Check for existence of the file using a wildcard, since we don't know which priority might have been used when enabling it. + typeset enabled_plugin=$(command ls "${BASH_IT}/$subdirectory/enabled/"{[0-9]*$BASH_IT_LOAD_PRIORITY_SEPARATOR$to_enable,$to_enable} 2>/dev/null | head -1) + if [ ! -z "$enabled_plugin" ] ; then + printf '%s\n' "$file_entity is already enabled." + return fi - mkdir -p $BASH_IT/$subdirectory/enabled + mkdir -p "${BASH_IT}/$subdirectory/enabled" - ln -s ../available/$plugin $BASH_IT/$subdirectory/enabled/$plugin + # Load the priority from the file if it present there + local local_file_priority=$(grep -E "^# BASH_IT_LOAD_PRIORITY:" "${BASH_IT}/$subdirectory/available/$to_enable" | awk -F': ' '{ print $2 }') + local use_load_priority=${local_file_priority:-$load_priority} + + ln -s ../available/$to_enable "${BASH_IT}/$subdirectory/enabled/${use_load_priority}${BASH_IT_LOAD_PRIORITY_SEPARATOR}${to_enable}" fi if [ -n "$BASH_IT_AUTOMATIC_RELOAD_AFTER_CONFIG_CHANGE" ]; then exec ${0/-/} fi - printf '%s\n' "$file_entity enabled." + printf '%s\n' "$file_entity enabled with priority $use_load_priority." } _help-completions() @@ -355,14 +415,14 @@ _help-aliases() alias_path="available/$1.aliases.bash" ;; esac - cat $BASH_IT/aliases/$alias_path | metafor alias | sed "s/$/'/" + cat "${BASH_IT}/aliases/$alias_path" | metafor alias | sed "s/$/'/" else typeset f - for f in $BASH_IT/aliases/enabled/* + for f in "${BASH_IT}/aliases/enabled/"* do _help-list-aliases $f done - _help-list-aliases $BASH_IT/aliases/custom.aliases.bash + _help-list-aliases "${BASH_IT}/aliases/custom.aliases.bash" fi } @@ -414,6 +474,14 @@ _help-update () { echo "Check for a new version of Bash-it and update it." } +_help-migrate () { + _about 'help message for migrate command' + _group 'lib' + + echo "Migrates internal Bash-it structure to the latest version in case of changes." + echo "The 'migrate' command is run automatically when calling 'update', 'enable' or 'disable'." +} + all_groups () { about 'displays all unique metadata groups' diff --git a/lib/preview.bash b/lib/preview.bash index 306b475a..d0fb0623 100644 --- a/lib/preview.bash +++ b/lib/preview.bash @@ -14,6 +14,6 @@ then BASH_IT_THEME=${BASH_IT_THEME##*/} echo " $BASH_IT_THEME" - echo "" | bash --init-file $BASH_IT/bash_it.sh -i + echo "" | bash --init-file "${BASH_IT}/bash_it.sh" -i done fi diff --git a/plugins/available/alias-completion.plugin.bash b/plugins/available/alias-completion.plugin.bash index c045c359..368d9f47 100644 --- a/plugins/available/alias-completion.plugin.bash +++ b/plugins/available/alias-completion.plugin.bash @@ -1,3 +1,6 @@ +# Load after the other completions to understand what needs to be completed +# BASH_IT_LOAD_PRIORITY: 365 + cite about-plugin about-plugin 'Automatic completion of aliases' diff --git a/plugins/available/base.plugin.bash b/plugins/available/base.plugin.bash index 411a20b2..5450a416 100755 --- a/plugins/available/base.plugin.bash +++ b/plugins/available/base.plugin.bash @@ -144,7 +144,7 @@ function usage () fi } -if [ ! -e $BASH_IT/plugins/enabled/todo.plugin.bash ]; then +if [ ! -e "${BASH_IT}/plugins/enabled/todo.plugin.bash" ] && [ ! -e "${BASH_IT}/plugins/enabled/*${BASH_IT_LOAD_PRIORITY_SEPARATOR}todo.plugin.bash" ]; then # if user has installed todo plugin, skip this... function t () { @@ -205,10 +205,10 @@ function buf () cp -a "${filename}" "${filename}_${filetime}" } -function del() { +function del() { about 'move files to hidden folder in tmp, that gets cleared on each reboot' param 'file or folder to be deleted' example 'del ./file.txt' group 'base' - mkdir -p /tmp/.trash && mv "$@" /tmp/.trash; + mkdir -p /tmp/.trash && mv "$@" /tmp/.trash; } diff --git a/plugins/available/fzf.plugin.bash b/plugins/available/fzf.plugin.bash index d96be3c9..aff89ea5 100644 --- a/plugins/available/fzf.plugin.bash +++ b/plugins/available/fzf.plugin.bash @@ -1,3 +1,6 @@ +# Load after the system completion to make sure that the fzf completions are working +# BASH_IT_LOAD_PRIORITY: 375 + cite about-plugin about-plugin 'load fzf, if you are using it' diff --git a/plugins/available/nvm.plugin.bash b/plugins/available/nvm.plugin.bash index 3959c236..e845d922 100644 --- a/plugins/available/nvm.plugin.bash +++ b/plugins/available/nvm.plugin.bash @@ -1,11 +1,13 @@ # Bash-it no longer bundles nvm, as this was quickly becoming outdated. # +# BASH_IT_LOAD_PRIORITY: 225 +# # Please install nvm from https://github.com/creationix/nvm.git if you want to use it. cite about-plugin about-plugin 'node version manager configuration' -export NVM_DIR="$HOME/.nvm" +export NVM_DIR=${NVM_DIR:-$HOME/.nvm} # This loads nvm if command -v brew &>/dev/null && [ -s $(brew --prefix nvm)/nvm.sh ] then diff --git a/plugins/available/z.plugin.bash b/plugins/available/z.plugin.bash index 66535756..7cfb7932 100644 --- a/plugins/available/z.plugin.bash +++ b/plugins/available/z.plugin.bash @@ -15,7 +15,7 @@ about-plugin ' z is DEPRECATED, use fasd instead' # * z -t foo # goes to most recently accessed dir matching foo # * z -l foo # list all dirs matching foo (by frecency) -if [ -e $BASH_IT/plugins/enabled/fasd.plugin.bash ]; then +if [ -e "${BASH_IT}/plugins/enabled/fasd.plugin.bash" ] || [ -e "${BASH_IT}/plugins/enabled/*${BASH_IT_LOAD_PRIORITY_SEPARATOR}fasd.plugin.bash" ]; then printf '%s\n' 'sorry, the z plugin is incompatible with the fasd plugin. you may use either, but not both.' return fi diff --git a/test/install/install.bats b/test/install/install.bats new file mode 100644 index 00000000..ded2689a --- /dev/null +++ b/test/install/install.bats @@ -0,0 +1,79 @@ +#!/usr/bin/env bats + +load ../test_helper +load ../../lib/composure + +# Determine which config file to use based on OS. +case $OSTYPE in + darwin*) + export BASH_IT_CONFIG_FILE=.bash_profile + ;; + *) + export BASH_IT_CONFIG_FILE=.bashrc + ;; +esac + +function local_setup { + mkdir -p $BASH_IT + lib_directory="$(cd "$(dirname "$0")" && pwd)" + cp -r $lib_directory/../../* $BASH_IT/ + rm -rf "$BASH_IT/aliases/enabled" "$BASH_IT/completion/enabled" "$BASH_IT/plugins/enabled" + + # Don't pollute the user's actual $HOME directory + # Use a test home directory instead + export BASH_IT_TEST_CURRENT_HOME="${HOME}" + export BASH_IT_TEST_HOME="$(cd "${BASH_IT}/.." && pwd)/BASH_IT_TEST_HOME" + mkdir -p "${BASH_IT_TEST_HOME}" + export HOME="${BASH_IT_TEST_HOME}" +} + +function local_teardown { + export HOME="${BASH_IT_TEST_CURRENT_HOME}" + + rm -rf "${BASH_IT_TEST_HOME}" + + assert_equal "${BASH_IT_TEST_CURRENT_HOME}" "${HOME}" +} + +@test "install: verify that the install script exists" { + assert [ -e "$BASH_IT/install.sh" ] +} + +@test "install: run the install script silently" { + cd "$BASH_IT" + + ./install.sh --silent + + assert [ -e "$BASH_IT_TEST_HOME/$BASH_IT_CONFIG_FILE" ] + + assert [ -L "$BASH_IT/aliases/enabled/150---general.aliases.bash" ] + assert [ -L "$BASH_IT/plugins/enabled/250---base.plugin.bash" ] + assert [ -L "$BASH_IT/plugins/enabled/365---alias-completion.plugin.bash" ] + assert [ -L "$BASH_IT/completion/enabled/350---bash-it.completion.bash" ] + assert [ -L "$BASH_IT/completion/enabled/350---system.completion.bash" ] +} + +@test "install: verify that a backup file is created" { + cd "$BASH_IT" + + touch "$BASH_IT_TEST_HOME/$BASH_IT_CONFIG_FILE" + echo "test file content" > "$BASH_IT_TEST_HOME/$BASH_IT_CONFIG_FILE" + local md5_orig=$(md5sum "$BASH_IT_TEST_HOME/$BASH_IT_CONFIG_FILE" | awk '{print $1}') + + ./install.sh --silent + + assert [ -e "$BASH_IT_TEST_HOME/$BASH_IT_CONFIG_FILE" ] + assert [ -e "$BASH_IT_TEST_HOME/$BASH_IT_CONFIG_FILE.bak" ] + + local md5_bak=$(md5sum "$BASH_IT_TEST_HOME/$BASH_IT_CONFIG_FILE.bak" | awk '{print $1}') + + assert_equal "$md5_orig" "$md5_bak" +} + +@test "install: verify that silent and interactive can not be used at the same time" { + cd "$BASH_IT" + + run ./install.sh --silent --interactive + + assert_failure +} diff --git a/test/install/uninstall.bats b/test/install/uninstall.bats new file mode 100644 index 00000000..adab216f --- /dev/null +++ b/test/install/uninstall.bats @@ -0,0 +1,78 @@ +#!/usr/bin/env bats + +load ../test_helper +load ../../lib/composure + +# Determine which config file to use based on OS. +case $OSTYPE in + darwin*) + export BASH_IT_CONFIG_FILE=.bash_profile + ;; + *) + export BASH_IT_CONFIG_FILE=.bashrc + ;; +esac + +function local_setup { + mkdir -p $BASH_IT + lib_directory="$(cd "$(dirname "$0")" && pwd)" + cp -r $lib_directory/../../* $BASH_IT/ + + # Don't pollute the user's actual $HOME directory + # Use a test home directory instead + export BASH_IT_TEST_CURRENT_HOME="${HOME}" + export BASH_IT_TEST_HOME="$(cd "${BASH_IT}/.." && pwd)/BASH_IT_TEST_HOME" + mkdir -p "${BASH_IT_TEST_HOME}" + export HOME="${BASH_IT_TEST_HOME}" +} + +function local_teardown { + export HOME="${BASH_IT_TEST_CURRENT_HOME}" + + rm -rf "${BASH_IT_TEST_HOME}" + + assert_equal "${BASH_IT_TEST_CURRENT_HOME}" "${HOME}" +} + +@test "uninstall: verify that the uninstall script exists" { + assert [ -e "$BASH_IT/uninstall.sh" ] +} + +@test "uninstall: run the uninstall script with an existing backup file" { + cd "$BASH_IT" + + echo "test file content for backup" > "$BASH_IT_TEST_HOME/$BASH_IT_CONFIG_FILE.bak" + echo "test file content for original file" > "$BASH_IT_TEST_HOME/$BASH_IT_CONFIG_FILE" + local md5_bak=$(md5sum "$BASH_IT_TEST_HOME/$BASH_IT_CONFIG_FILE.bak" | awk '{print $1}') + + ./uninstall.sh + + assert_success + + assert [ ! -e "$BASH_IT_TEST_HOME/$BASH_IT_CONFIG_FILE.uninstall" ] + assert [ ! -e "$BASH_IT_TEST_HOME/$BASH_IT_CONFIG_FILE.bak" ] + assert [ -e "$BASH_IT_TEST_HOME/$BASH_IT_CONFIG_FILE" ] + + local md5_conf=$(md5sum "$BASH_IT_TEST_HOME/$BASH_IT_CONFIG_FILE" | awk '{print $1}') + + assert_equal "$md5_bak" "$md5_conf" +} + +@test "uninstall: run the uninstall script without an existing backup file" { + cd "$BASH_IT" + + echo "test file content for original file" > "$BASH_IT_TEST_HOME/$BASH_IT_CONFIG_FILE" + local md5_orig=$(md5sum "$BASH_IT_TEST_HOME/$BASH_IT_CONFIG_FILE" | awk '{print $1}') + + ./uninstall.sh + + assert_success + + assert [ -e "$BASH_IT_TEST_HOME/$BASH_IT_CONFIG_FILE.uninstall" ] + assert [ ! -e "$BASH_IT_TEST_HOME/$BASH_IT_CONFIG_FILE.bak" ] + assert [ ! -e "$BASH_IT_TEST_HOME/$BASH_IT_CONFIG_FILE" ] + + local md5_uninstall=$(md5sum "$BASH_IT_TEST_HOME/$BASH_IT_CONFIG_FILE.uninstall" | awk '{print $1}') + + assert_equal "$md5_orig" "$md5_uninstall" +} diff --git a/test/lib/helpers.bats b/test/lib/helpers.bats index 4f3e4ffa..00b13b3a 100644 --- a/test/lib/helpers.bats +++ b/test/lib/helpers.bats @@ -1,5 +1,6 @@ #!/usr/bin/env bats +load ../test_helper load ../../lib/composure load ../../plugins/available/base.plugin @@ -7,4 +8,233 @@ cite _about _param _example _group _author _version load ../../lib/helpers -## TODO: write some tests. +function local_setup { + mkdir -p $BASH_IT + lib_directory="$(cd "$(dirname "$0")" && pwd)" + cp -r $lib_directory/../.. $BASH_IT + mkdir -p $BASH_IT/aliases/enabled + mkdir -p $BASH_IT/completion/enabled + mkdir -p $BASH_IT/plugins/enabled +} + +@test "bash-it: enable the ansible aliases through the bash-it function" { + run bash-it enable alias "ansible" + assert_line "0" 'ansible enabled with priority 150.' + assert [ -L "$BASH_IT/aliases/enabled/150---ansible.aliases.bash" ] +} + +@test "bash-it: enable the todo.txt-cli aliases through the bash-it function" { + run bash-it enable alias "todo.txt-cli" + assert_line "0" 'todo.txt-cli enabled with priority 150.' + assert [ -L "$BASH_IT/aliases/enabled/150---todo.txt-cli.aliases.bash" ] +} + +@test "bash-it: enable the curl aliases" { + run _enable-alias "curl" + assert_line "0" 'curl enabled with priority 150.' + assert [ -L "$BASH_IT/aliases/enabled/150---curl.aliases.bash" ] +} + +@test "bash-it: enable the apm completion through the bash-it function" { + run bash-it enable completion "apm" + assert_line "0" 'apm enabled with priority 350.' + assert [ -L "$BASH_IT/completion/enabled/350---apm.completion.bash" ] +} + +@test "bash-it: enable the brew completion" { + run _enable-completion "brew" + assert_line "0" 'brew enabled with priority 350.' + assert [ -L "$BASH_IT/completion/enabled/350---brew.completion.bash" ] +} + +@test "bash-it: enable the node plugin" { + run _enable-plugin "node" + assert_line "0" 'node enabled with priority 250.' + assert [ -L "$BASH_IT/plugins/enabled/250---node.plugin.bash" ] +} + +@test "bash-it: enable the node plugin through the bash-it function" { + run bash-it enable plugin "node" + assert_line "0" 'node enabled with priority 250.' + assert [ -L "$BASH_IT/plugins/enabled/250---node.plugin.bash" ] +} + +@test "bash-it: enable the node and nvm plugins through the bash-it function" { + run bash-it enable plugin "node" "nvm" + assert_line "0" 'node enabled with priority 250.' + assert_line "1" 'nvm enabled with priority 225.' + assert [ -L "$BASH_IT/plugins/enabled/250---node.plugin.bash" ] + assert [ -L "$BASH_IT/plugins/enabled/225---nvm.plugin.bash" ] +} + +@test "bash-it: enable the foo-unkown and nvm plugins through the bash-it function" { + run bash-it enable plugin "foo-unknown" "nvm" + assert_line "0" 'sorry, foo-unknown does not appear to be an available plugin.' + assert_line "1" 'nvm enabled with priority 225.' + assert [ -L "$BASH_IT/plugins/enabled/225---nvm.plugin.bash" ] +} + +@test "bash-it: enable the nvm plugin" { + run _enable-plugin "nvm" + assert_line "0" 'nvm enabled with priority 225.' + assert [ -L "$BASH_IT/plugins/enabled/225---nvm.plugin.bash" ] +} + +@test "bash-it: enable an unknown plugin" { + run _enable-plugin "unknown-foo" + assert_line "0" 'sorry, unknown-foo does not appear to be an available plugin.' + assert [ ! -L "$BASH_IT/plugins/enabled/250---unknown-foo.plugin.bash" ] + assert [ ! -L "$BASH_IT/plugins/enabled/unknown-foo.plugin.bash" ] +} + +@test "bash-it: enable an unknown plugin through the bash-it function" { + run bash-it enable plugin "unknown-foo" + echo "${lines[@]}" + assert_line "0" 'sorry, unknown-foo does not appear to be an available plugin.' + assert [ ! -L "$BASH_IT/plugins/enabled/250---unknown-foo.plugin.bash" ] + assert [ ! -L "$BASH_IT/plugins/enabled/unknown-foo.plugin.bash" ] +} + +@test "bash-it: disable a plugin that is not enabled" { + run _disable-plugin "sdkman" + assert_line "0" 'sorry, sdkman does not appear to be an enabled plugin.' +} + +@test "bash-it: enable and disable the nvm plugin" { + run _enable-plugin "nvm" + assert_line "0" 'nvm enabled with priority 225.' + assert [ -L "$BASH_IT/plugins/enabled/225---nvm.plugin.bash" ] + + run _disable-plugin "nvm" + assert_line "0" 'nvm disabled.' + assert [ ! -L "$BASH_IT/plugins/enabled/225---nvm.plugin.bash" ] +} + +@test "bash-it: disable the nvm plugin if it was enabled without a priority" { + ln -s $BASH_IT/plugins/available/nvm.plugin.bash $BASH_IT/plugins/enabled/nvm.plugin.bash + assert [ -L "$BASH_IT/plugins/enabled/nvm.plugin.bash" ] + + run _disable-plugin "nvm" + assert_line "0" 'nvm disabled.' + assert [ ! -L "$BASH_IT/plugins/enabled/nvm.plugin.bash" ] +} + +@test "bash-it: enable the nvm plugin if it was enabled without a priority" { + ln -s $BASH_IT/plugins/available/nvm.plugin.bash $BASH_IT/plugins/enabled/nvm.plugin.bash + assert [ -L "$BASH_IT/plugins/enabled/nvm.plugin.bash" ] + + run _enable-plugin "nvm" + assert_line "0" 'nvm is already enabled.' + assert [ -L "$BASH_IT/plugins/enabled/nvm.plugin.bash" ] + assert [ ! -L "$BASH_IT/plugins/enabled/225---nvm.plugin.bash" ] +} + +@test "bash-it: enable the nvm plugin twice" { + run _enable-plugin "nvm" + assert_line "0" 'nvm enabled with priority 225.' + assert [ -L "$BASH_IT/plugins/enabled/225---nvm.plugin.bash" ] + + run _enable-plugin "nvm" + assert_line "0" 'nvm is already enabled.' + assert [ -L "$BASH_IT/plugins/enabled/225---nvm.plugin.bash" ] +} + +@test "bash-it: migrate enabled plugins that don't use the new priority-based configuration" { + ln -s $BASH_IT/plugins/available/nvm.plugin.bash $BASH_IT/plugins/enabled/nvm.plugin.bash + assert [ -L "$BASH_IT/plugins/enabled/nvm.plugin.bash" ] + + ln -s $BASH_IT/plugins/available/node.plugin.bash $BASH_IT/plugins/enabled/node.plugin.bash + assert [ -L "$BASH_IT/plugins/enabled/node.plugin.bash" ] + + ln -s $BASH_IT/aliases/available/todo.txt-cli.aliases.bash $BASH_IT/aliases/enabled/todo.txt-cli.aliases.bash + assert [ -L "$BASH_IT/aliases/enabled/todo.txt-cli.aliases.bash" ] + + run _enable-plugin "ssh" + assert [ -L "$BASH_IT/plugins/enabled/250---ssh.plugin.bash" ] + + run _bash-it-migrate + assert [ -L "$BASH_IT/plugins/enabled/225---nvm.plugin.bash" ] + assert [ -L "$BASH_IT/plugins/enabled/250---node.plugin.bash" ] + assert [ -L "$BASH_IT/plugins/enabled/250---ssh.plugin.bash" ] + assert [ -L "$BASH_IT/aliases/enabled/150---todo.txt-cli.aliases.bash" ] + assert [ ! -L "$BASH_IT/plugins/enabled/node.plugin.bash" ] + assert [ ! -L "$BASH_IT/plugins/enabled/nvm.plugin.bash" ] + assert [ ! -L "$BASH_IT/aliases/enabled/todo.txt-cli.aliases.bash" ] +} + +@test "bash-it: run the migrate command without anything to migrate and nothing enabled" { + run _bash-it-migrate +} + +@test "bash-it: run the migrate command without anything to migrate" { + run _enable-plugin "ssh" + assert [ -L "$BASH_IT/plugins/enabled/250---ssh.plugin.bash" ] + + run _bash-it-migrate + assert [ -L "$BASH_IT/plugins/enabled/250---ssh.plugin.bash" ] +} + +@test "bash-it: verify that existing components are automatically migrated when something is enabled" { + ln -s $BASH_IT/plugins/available/nvm.plugin.bash $BASH_IT/plugins/enabled/nvm.plugin.bash + assert [ -L "$BASH_IT/plugins/enabled/nvm.plugin.bash" ] + + run bash-it enable plugin "node" + assert_line "0" 'Migrating plugin nvm.' + assert_line "1" 'nvm disabled.' + assert_line "2" 'nvm enabled with priority 225.' + assert_line "3" 'node enabled with priority 250.' + assert [ ! -L "$BASH_IT/plugins/enabled/nvm.plugin.bash" ] + assert [ -L "$BASH_IT/plugins/enabled/225---nvm.plugin.bash" ] + assert [ -L "$BASH_IT/plugins/enabled/250---node.plugin.bash" ] +} + +@test "bash-it: verify that existing components are automatically migrated when something is disabled" { + ln -s $BASH_IT/plugins/available/nvm.plugin.bash $BASH_IT/plugins/enabled/nvm.plugin.bash + assert [ -L "$BASH_IT/plugins/enabled/nvm.plugin.bash" ] + ln -s $BASH_IT/plugins/available/node.plugin.bash $BASH_IT/plugins/enabled/250---node.plugin.bash + assert [ -L "$BASH_IT/plugins/enabled/250---node.plugin.bash" ] + + run bash-it disable plugin "node" + assert_line "0" 'Migrating plugin nvm.' + assert_line "1" 'nvm disabled.' + assert_line "2" 'nvm enabled with priority 225.' + assert_line "3" 'node disabled.' + assert [ ! -L "$BASH_IT/plugins/enabled/nvm.plugin.bash" ] + assert [ -L "$BASH_IT/plugins/enabled/225---nvm.plugin.bash" ] + assert [ ! -L "$BASH_IT/plugins/enabled/250---node.plugin.bash" ] +} + +@test "bash-it: enable all plugins" { + run _enable-plugin "all" + local available=$(find $BASH_IT/plugins/available -name *.plugin.bash | wc -l | xargs) + local enabled=$(find $BASH_IT/plugins/enabled -name [0-9]*.plugin.bash | wc -l | xargs) + assert_equal "$available" "$enabled" +} + +@test "bash-it: disable all plugins" { + run _enable-plugin "all" + local available=$(find $BASH_IT/plugins/available -name *.plugin.bash | wc -l | xargs) + local enabled=$(find $BASH_IT/plugins/enabled -name [0-9]*.plugin.bash | wc -l | xargs) + assert_equal "$available" "$enabled" + + run _disable-plugin "all" + local enabled2=$(find $BASH_IT/plugins/enabled -name *.plugin.bash | wc -l | xargs) + assert_equal "$enabled2" "0" +} + +@test "bash-it: describe the nvm plugin without enabling it" { + _bash-it-plugins | grep "nvm" | grep "\[ \]" +} + +@test "bash-it: describe the nvm plugin after enabling it" { + run _enable-plugin "nvm" + assert_line "0" 'nvm enabled with priority 225.' + assert [ -L "$BASH_IT/plugins/enabled/225---nvm.plugin.bash" ] + + _bash-it-plugins | grep "nvm" | grep "\[x\]" +} + +@test "bash-it: describe the todo.txt-cli aliases without enabling them" { + run _bash-it-aliases + assert_line "todo.txt-cli [ ] todo.txt-cli abbreviations" +} diff --git a/test/lib/search.bats b/test/lib/search.bats index ae9e9a89..71a176d4 100644 --- a/test/lib/search.bats +++ b/test/lib/search.bats @@ -1,5 +1,7 @@ #!/usr/bin/env bats +load ../test_helper + load ../../lib/composure load ../../plugins/available/base.plugin @@ -10,44 +12,50 @@ load ../../lib/search NO_COLOR=true -@test "helpers search aliases" { +function local_setup { + mkdir -p $BASH_IT + lib_directory="$(cd "$(dirname "$0")" && pwd)" + cp -r $lib_directory/../../* $BASH_IT/ +} + +@test "helpers search plugins" { run _bash-it-search-component 'plugins' 'base' [[ "${lines[0]}" =~ 'plugins' && "${lines[0]}" =~ 'base' ]] } @test "helpers search ruby gem bundle rake rails" { # first disable them all, so that the output does not appear with a checkbox - # and we can compoare the result + # and we can compare the result run _bash-it-search 'ruby' 'gem' 'bundle' 'rake' 'rails' '--disable' # Now perform the search run _bash-it-search 'ruby' 'gem' 'bundle' 'rake' 'rails' # And verify - [[ "${lines[0]/✓/}" == ' aliases => bundler rails' ]] && \ - [[ "${lines[1]/✓/}" == ' plugins => chruby chruby-auto rails ruby' ]] && \ - [[ "${lines[2]/✓/}" == ' completions => bundler gem rake' ]] + assert [ "${lines[0]/✓/}" == ' aliases => bundler rails' ] + assert [ "${lines[1]/✓/}" == ' plugins => chruby chruby-auto rails ruby' ] + assert [ "${lines[2]/✓/}" == ' completions => bundler gem rake' ] } @test "search ruby gem bundle -chruby rake rails" { run _bash-it-search 'ruby' 'gem' 'bundle' 'rake' 'rails' '--disable' run _bash-it-search 'ruby' 'gem' 'bundle' '-chruby' 'rake' 'rails' - [[ "${lines[0]/✓/}" == ' aliases => bundler rails' ]] && \ - [[ "${lines[1]/✓/}" == ' plugins => rails ruby' ]] && \ - [[ "${lines[2]/✓/}" == ' completions => bundler gem rake' ]] + assert [ "${lines[0]/✓/}" == ' aliases => bundler rails' ] + assert [ "${lines[1]/✓/}" == ' plugins => rails ruby' ] + assert [ "${lines[2]/✓/}" == ' completions => bundler gem rake' ] } @test "search (rails enabled) ruby gem bundle rake rails" { run _bash-it-search 'ruby' 'gem' 'bundle' 'rake' 'rails' '--disable' run _enable-alias 'rails' run _bash-it-search 'ruby' 'gem' 'bundle' 'rake' 'rails' - [[ "${lines[0]}" == ' aliases => bundler ✓rails' ]] && \ - [[ "${lines[1]}" == ' plugins => chruby chruby-auto rails ruby' ]] && \ - [[ "${lines[2]}" == ' completions => bundler gem rake' ]] + assert_line "0" ' aliases => bundler ✓rails' + assert_line "1" ' plugins => chruby chruby-auto rails ruby' + assert_line "2" ' completions => bundler gem rake' } @test "search (all enabled) ruby gem bundle rake rails" { run _bash-it-search 'ruby' 'gem' 'bundle' 'rake' '-chruby' 'rails' '--enable' run _bash-it-search 'ruby' 'gem' 'bundle' 'rake' '-chruby' 'rails' - [[ "${lines[0]}" == ' aliases => ✓bundler ✓rails' ]] && \ - [[ "${lines[1]}" == ' plugins => ✓rails ✓ruby' ]] && \ - [[ "${lines[2]}" == ' completions => ✓bundler ✓gem ✓rake' ]] + assert_line "0" ' aliases => ✓bundler ✓rails' + assert_line "1" ' plugins => ✓rails ✓ruby' + assert_line "2" ' completions => ✓bundler ✓gem ✓rake' } diff --git a/test/plugins/base.plugin.bats b/test/plugins/base.plugin.bats index 3b21ca7f..a27a4ae7 100755 --- a/test/plugins/base.plugin.bats +++ b/test/plugins/base.plugin.bats @@ -52,5 +52,5 @@ load ../../plugins/available/base.plugin declare -r file="${BASH_IT_ROOT}/file" touch $file run buf $file - [[ -e ${file}_$(date +%Y%m%d_%H%M%S) ]] + assert [ -e ${file}_$(date +%Y%m%d_%H%M%S) ] } diff --git a/test/run b/test/run index 397aec9c..737f17e2 100755 --- a/test/run +++ b/test/run @@ -9,4 +9,4 @@ if [ -z "${BASH_IT}" ]; then export BASH_IT=$(cd ${test_directory} && dirname $(pwd)) fi -exec $bats_executable ${CI:+--tap} ${test_directory}/{lib,plugins} +exec $bats_executable ${CI:+--tap} ${test_directory}/{install,lib,plugins,themes} diff --git a/test/test_helper.bash b/test/test_helper.bash index 71b3a16c..08638b54 100644 --- a/test/test_helper.bash +++ b/test/test_helper.bash @@ -13,11 +13,23 @@ if [ "$BASH_IT_ROOT" != "${BASH_IT_TEST_DIR}/root" ]; then export BASH_IT=$BASH_IT_TEST_DIR fi +local_setup() { + true +} + +local_teardown() { + true +} + setup() { mkdir -p -- "${BASH_IT_ROOT}" + + local_setup } teardown() { + local_teardown + rm -rf "${BASH_IT_TEST_DIR}" } diff --git a/test/themes/base.theme.bats b/test/themes/base.theme.bats new file mode 100644 index 00000000..6bf7efed --- /dev/null +++ b/test/themes/base.theme.bats @@ -0,0 +1,69 @@ +#!/usr/bin/env bats + +load ../test_helper +load ../../lib/composure +load ../../plugins/available/base.plugin +load ../../themes/base.theme + +@test 'themes base: battery_percentage should not exist' { + run type -a battery_percentage &> /dev/null + assert_failure +} + +@test 'themes base: battery_percentage should exist if battery plugin loaded' { + load ../../plugins/available/battery.plugin + + run type -a battery_percentage &> /dev/null + assert_success +} + +@test 'themes base: battery_char should exist' { + run type -a battery_char &> /dev/null + assert_success + + run battery_char + assert_success + assert_line "0" "" + + run type -a battery_char + assert_line " echo -n" +} + +@test 'themes base: battery_char should exist if battery plugin loaded' { + unset -f battery_char + load ../../plugins/available/battery.plugin + load ../../themes/base.theme + + run type -a battery_char &> /dev/null + assert_success + + run battery_char + assert_success + + run type -a battery_char + assert_line ' if [[ "${THEME_BATTERY_PERCENTAGE_CHECK}" = true ]]; then' +} + +@test 'themes base: battery_charge should exist' { + run type -a battery_charge &> /dev/null + assert_success + + run battery_charge + assert_success + assert_line "0" "" +} + +@test 'themes base: battery_charge should exist if battery plugin loaded' { + unset -f battery_charge + load ../../plugins/available/battery.plugin + load ../../themes/base.theme + + run type -a battery_charge &> /dev/null + assert_success + + run battery_charge + assert_success + + run type -a battery_charge + assert_line ' no)' +} diff --git a/themes/atomic/README.md b/themes/atomic/README.md index ddfff4d0..db01a80f 100644 --- a/themes/atomic/README.md +++ b/themes/atomic/README.md @@ -1,6 +1,6 @@ # Atomic theme -Simple colorful terminal prompt theme (inspired by a number of themes and it is based mainly on the theme of @MunifTanjim [`brainy`](themes/brainy/README.md)). +The Best ColorFull terminal prompt theme inspired by a number of themes and based on the theme of @MunifTanjim [`brainy`](../brainy/README.md). Supported on all operating systems. @@ -155,6 +155,15 @@ Three environment variables can be defined to rearrange the segments order. The `___ATOMIC_TOP_LEFT="user_info dir scm"` -`___ATOMIC_TOP_RIGHT="python ruby todo clock battery"` +`___ATOMIC_TOP_RIGHT="exitcode python ruby todo clock battery"` -`___ATOMIC_BOTTOM="exitcode char"` +`___ATOMIC_BOTTOM="char"` + +## Follow me + +I'm on the social media. + +* [@lfelipe1501](https://twitter.com/lfelipe1501) on Twitter. +* [Luis Felipe](https://www.facebook.com/lfelipe1501) on Facebook. + +This work is licensed under the Creative Commons Attribution 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by/4.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA. diff --git a/themes/atomic/atomic.theme.bash b/themes/atomic/atomic.theme.bash index 8ac18dfd..3df4e7ce 100644 --- a/themes/atomic/atomic.theme.bash +++ b/themes/atomic/atomic.theme.bash @@ -164,8 +164,10 @@ ___atomic_prompt_clock() { } ___atomic_prompt_battery() { - chk=$(command_exists battery_percentage && echo yes || echo no) - [ "$chk" != "yes" ] || [ "${THEME_SHOW_BATTERY}" != "true" ] && return + ! command_exists battery_percentage || + [ "${THEME_SHOW_BATTERY}" != "true" ] || + [ "$(battery_percentage)" = "no" ] && return + batp=$(battery_percentage) if [ "$batp" -eq 50 ] || [ "$batp" -gt 50 ]; then color=$bold_green @@ -178,7 +180,7 @@ ___atomic_prompt_battery() { ac_adapter_disconnected && info="-" ac_adapter_connected && info="+" info+=$batp - [ "$info" == "+100" ] && info="AC" + [ "$batp" -eq 100 ] || [ "$batp" -gt 100 ] && info="AC" printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_white}" "${box}" } diff --git a/themes/base.theme.bash b/themes/base.theme.bash index 84928acd..58e2d288 100644 --- a/themes/base.theme.bash +++ b/themes/base.theme.bash @@ -474,13 +474,17 @@ function battery_char { fi } -if [ ! -e "$BASH_IT"/plugins/enabled/battery.plugin.bash ]; then +if ! command_exists battery_charge ; then # if user has installed battery plugin, skip this... function battery_charge (){ # no op echo -n } +fi +# The battery_char function depends on the presence of the battery_percentage function. +# If battery_percentage is not defined, then define battery_char as a no-op. +if ! command_exists battery_percentage ; then function battery_char (){ # no op echo -n diff --git a/themes/brainy/brainy.theme.bash b/themes/brainy/brainy.theme.bash index e840c004..54d29f8b 100644 --- a/themes/brainy/brainy.theme.bash +++ b/themes/brainy/brainy.theme.bash @@ -152,8 +152,10 @@ ___brainy_prompt_clock() { } ___brainy_prompt_battery() { - [ ! -e $BASH_IT/plugins/enabled/battery.plugin.bash ] || - [ "${THEME_SHOW_BATTERY}" != "true" ] && return + ! command_exists battery_percentage || + [ "${THEME_SHOW_BATTERY}" != "true" ] || + [ "$(battery_percentage)" = "no" ] && return + info=$(battery_percentage) color=$bold_green if [ "$info" -lt 50 ]; then diff --git a/themes/demula/demula.theme.bash b/themes/demula/demula.theme.bash index ed03a708..e698def5 100644 --- a/themes/demula/demula.theme.bash +++ b/themes/demula/demula.theme.bash @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/usr/bin/env bash # Theme inspired on: # - Ronacher's dotfiles (mitsuhikos) - http://github.com/mitsuhiko/dotfiles/tree/master/bash/ @@ -10,7 +10,7 @@ # Screenshot: http://goo.gl/VCmX5 # by Jesus de Mula -# For the real Monokai colors you should add these to your .XDefaults or +# For the real Monokai colors you should add these to your .XDefaults or # terminal configuration: #! ----------------------------------------------------------- TERMINAL COLORS #! monokai - http://www.monokai.nl/blog/2006/07/15/textmate-color-theme/ @@ -68,7 +68,7 @@ mitsuhikos_lastcommandfailed() { if [ $code != 0 ]; then echo "${D_INTERMEDIATE_COLOR}exited ${D_CMDFAIL_COLOR}\ -$code ${D_DEFAULT_COLOR}" +$code ${D_DEFAULT_COLOR}" fi } @@ -78,13 +78,13 @@ demula_vcprompt() { then local D_VCPROMPT_FORMAT="on ${D_SCM_COLOR}%s${D_INTERMEDIATE_COLOR}:\ ${D_BRANCH_COLOR}%b %r ${D_CHANGES_COLOR}%m%u ${D_DEFAULT_COLOR}" - $VCPROMPT_EXECUTABLE -f "$D_VCPROMPT_FORMAT" + $VCPROMPT_EXECUTABLE -f "$D_VCPROMPT_FORMAT" fi } # checks if the plugin is installed before calling battery_charge safe_battery_charge() { - if [ -e "${BASH_IT}/plugins/enabled/battery.plugin.bash" ]; + if command_exists battery_charge ; then battery_charge fi @@ -127,4 +127,3 @@ ${D_INTERMEDIATE_COLOR}$ ${D_DEFAULT_COLOR}" # Runs prompt (this bypasses bash_it $PROMPT setting) safe_append_prompt_command prompt - diff --git a/themes/iterate/iterate.theme.bash b/themes/iterate/iterate.theme.bash index 2031b7fc..cf682a9f 100644 --- a/themes/iterate/iterate.theme.bash +++ b/themes/iterate/iterate.theme.bash @@ -52,7 +52,7 @@ function prompt_command() { fi local wrap_char="" - [[ ${#new_PS1} -gt $(($COLUMNS/1)) ]] && wrap_char="\n" + [[ $COLUMNS && ${#new_PS1} > $(($COLUMNS/1)) ]] && wrap_char="\n" PS1="${new_PS1}${green}${wrap_char}→${reset_color} " } diff --git a/themes/rana/rana.theme.bash b/themes/rana/rana.theme.bash index c1122429..0aed8348 100644 --- a/themes/rana/rana.theme.bash +++ b/themes/rana/rana.theme.bash @@ -117,7 +117,7 @@ ${D_BRANCH_COLOR}%b %r ${D_CHANGES_COLOR}%m%u ${D_DEFAULT_COLOR}" # checks if the plugin is installed before calling battery_charge safe_battery_charge() { - if [ -e "${BASH_IT}/plugins/enabled/battery.plugin.bash" ]; + if command_exists battery_charge ; then battery_charge fi