Merge branch 'master' of git://github.com/Bash-it/bash-it into issue-1206

pull/1991/head
noviicee 2022-01-03 23:38:33 +05:30
commit 201827ddff
33 changed files with 1419 additions and 632 deletions

5
.gitignore vendored
View File

@ -17,3 +17,8 @@ bats
enabled/* enabled/*
/enabled /enabled
tmp/ tmp/
# Do not save profiles
profiles/*
# apart from the default one
!profiles/default.bash_it

View File

@ -137,13 +137,6 @@ elif [ -s /Applications/Preview.app ]; then
PREVIEW="/Applications/Preview.app" PREVIEW="/Applications/Preview.app"
fi fi
# Load all the Jekyll stuff
if [ -e "$HOME/.jekyllconfig" ]; then
# shellcheck disable=SC1090
. "$HOME/.jekyllconfig"
fi
# BASH_IT_RELOAD_LEGACY is set. # BASH_IT_RELOAD_LEGACY is set.
if ! _command_exists reload && [[ -n "${BASH_IT_RELOAD_LEGACY:-}" ]]; then if ! _command_exists reload && [[ -n "${BASH_IT_RELOAD_LEGACY:-}" ]]; then
case $OSTYPE in case $OSTYPE in

View File

@ -97,6 +97,8 @@ plugins/available/history-search.plugin.bash
plugins/available/history-substring-search.plugin.bash plugins/available/history-substring-search.plugin.bash
plugins/available/history.plugin.bash plugins/available/history.plugin.bash
plugins/available/hub.plugin.bash plugins/available/hub.plugin.bash
plugins/available/java.plugin.bash
plugins/available/jekyll.plugin.bash
plugins/available/jump.plugin.bash plugins/available/jump.plugin.bash
plugins/available/less-pretty-cat.plugin.bash plugins/available/less-pretty-cat.plugin.bash
plugins/available/node.plugin.bash plugins/available/node.plugin.bash

View File

@ -57,6 +57,18 @@ _bash-it-comp-list-available()
COMPREPLY=( $(compgen -W "${enabled_things}" -- ${cur}) ) COMPREPLY=( $(compgen -W "${enabled_things}" -- ${cur}) )
} }
_bash-it-comp-list-profiles()
{
local profiles
profiles=$(for f in `compgen -G "${BASH_IT}/profiles/*.bash_it" | sort -d`;
do
basename $f | sed -e 's/.bash_it//g'
done)
COMPREPLY=( $(compgen -W "${profiles}" -- ${cur}) )
}
_bash-it-comp() _bash-it-comp()
{ {
local cur prev opts local cur prev opts
@ -65,7 +77,7 @@ _bash-it-comp()
prev="${COMP_WORDS[COMP_CWORD-1]}" prev="${COMP_WORDS[COMP_CWORD-1]}"
chose_opt="${COMP_WORDS[1]}" chose_opt="${COMP_WORDS[1]}"
file_type="${COMP_WORDS[2]}" file_type="${COMP_WORDS[2]}"
opts="disable enable help migrate reload restart doctor search show update version" opts="disable enable help migrate reload restart profile doctor search show update version"
case "${chose_opt}" in case "${chose_opt}" in
show) show)
local show_args="aliases completions plugins" local show_args="aliases completions plugins"
@ -82,6 +94,33 @@ _bash-it-comp()
return 0 return 0
fi fi
;; ;;
profile)
case "${file_type}" in
load)
if [[ "load" == "$prev" ]]; then
_bash-it-comp-list-profiles
fi
return 0
;;
rm)
if [[ "rm" == "$prev" ]]; then
_bash-it-comp-list-profiles
fi
return 0
;;
save)
return 0
;;
list)
return 0
;;
*)
local profile_args="load save list rm"
COMPREPLY=( $(compgen -W "${profile_args}" -- ${cur}) )
return 0
;;
esac
;;
doctor) doctor)
local doctor_args="errors warnings all" local doctor_args="errors warnings all"
COMPREPLY=( $(compgen -W "${doctor_args}" -- ${cur}) ) COMPREPLY=( $(compgen -W "${doctor_args}" -- ${cur}) )

View File

@ -1,175 +1,5 @@
# defaults # shellcheck shell=bash
# Bash command line completion for defaults
#
# Created by Jonathon Mah on 2006-11-08.
# Copyright 2006 Playhaus. All rights reserved.
#
# Version 1.0 (2006-11-08)
if test -s "${BASH_IT?}/vendor/github.com/gaelicWizard/bash-progcomp/defaults.completion.bash"; then
_defaults_domains() source "$_"
{
local cur
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
local domains=$( defaults domains | sed -e 's/, /:/g' | tr : '\n' | sed -e 's/ /\\ /g' | grep "^$cur" )
local IFS=$'\n'
COMPREPLY=( $domains )
if [[ $( echo '-app' | grep "^$cur" ) ]]; then
COMPREPLY[${#COMPREPLY[@]}]="-app"
fi fi
return 0
}
_defaults()
{
local cur prev host_opts cmds cmd domain keys key_index
cur=${COMP_WORDS[COMP_CWORD]}
prev=${COMP_WORDS[COMP_CWORD-1]}
host_opts='-currentHost -host'
cmds='read read-type write rename delete domains find help'
if [[ $COMP_CWORD -eq 1 ]]; then
COMPREPLY=( $( compgen -W "$host_opts $cmds" -- $cur ) )
return 0
elif [[ $COMP_CWORD -eq 2 ]]; then
if [[ "$prev" == "-currentHost" ]]; then
COMPREPLY=( $( compgen -W "$cmds" -- $cur ) )
return 0
elif [[ "$prev" == "-host" ]]; then
_known_hosts -a
return 0
else
_defaults_domains
return 0
fi
elif [[ $COMP_CWORD -eq 3 ]]; then
if [[ ${COMP_WORDS[1]} == "-host" ]]; then
_defaults_domains
return 0
fi
fi
# Both a domain and command have been specified
if [[ ${COMP_WORDS[1]} == [${cmds// /|}] ]]; then
cmd=${COMP_WORDS[1]}
domain=${COMP_WORDS[2]}
key_index=3
if [[ "$domain" == "-app" ]]; then
if [[ $COMP_CWORD -eq 3 ]]; then
# Completing application name. Can't help here, sorry
return 0
fi
domain="-app ${COMP_WORDS[3]}"
key_index=4
fi
elif [[ ${COMP_WORDS[2]} == "-currentHost" ]] && [[ ${COMP_WORDS[2]} == [${cmds// /|}] ]]; then
cmd=${COMP_WORDS[2]}
domain=${COMP_WORDS[3]}
key_index=4
if [[ "$domain" == "-app" ]]; then
if [[ $COMP_CWORD -eq 4 ]]; then
# Completing application name. Can't help here, sorry
return 0
fi
domain="-app ${COMP_WORDS[4]}"
key_index=5
fi
elif [[ ${COMP_WORDS[3]} == "-host" ]] && [[ ${COMP_WORDS[3]} == [${cmds// /|}] ]]; then
cmd=${COMP_WORDS[3]}
domain=${COMP_WORDS[4]}
key_index=5
if [[ "$domain" == "-app" ]]; then
if [[ $COMP_CWORD -eq 5 ]]; then
# Completing application name. Can't help here, sorry
return 0
fi
domain="-app ${COMP_WORDS[5]}"
key_index=6
fi
fi
keys=$( defaults read $domain 2>/dev/null | sed -n -e '/^ [^}) ]/p' | sed -e 's/^ \([^" ]\{1,\}\) = .*$/\1/g' -e 's/^ "\([^"]\{1,\}\)" = .*$/\1/g' | sed -e 's/ /\\ /g' )
case $cmd in
read|read-type)
# Complete key
local IFS=$'\n'
COMPREPLY=( $( echo "$keys" | grep -i "^${cur//\\/\\\\}" ) )
;;
write)
if [[ $key_index -eq $COMP_CWORD ]]; then
# Complete key
local IFS=$'\n'
COMPREPLY=( $( echo "$keys" | grep -i "^${cur//\\/\\\\}" ) )
elif [[ $((key_index+1)) -eq $COMP_CWORD ]]; then
# Complete value type
# Unfortunately ${COMP_WORDS[key_index]} fails on keys with spaces
local value_types='-string -data -integer -float -boolean -date -array -array-add -dict -dict-add'
local cur_type=$( defaults read-type $domain ${COMP_WORDS[key_index]} 2>/dev/null | sed -e 's/^Type is \(.*\)/-\1/' -e's/dictionary/dict/' | grep "^$cur" )
if [[ $cur_type ]]; then
COMPREPLY=( $cur_type )
else
COMPREPLY=( $( compgen -W "$value_types" -- $cur ) )
fi
elif [[ $((key_index+2)) -eq $COMP_CWORD ]]; then
# Complete value
# Unfortunately ${COMP_WORDS[key_index]} fails on keys with spaces
COMPREPLY=( $( defaults read $domain ${COMP_WORDS[key_index]} 2>/dev/null | grep -i "^${cur//\\/\\\\}" ) )
fi
;;
rename)
if [[ $key_index -eq $COMP_CWORD ]] ||
[[ $((key_index+1)) -eq $COMP_CWORD ]]; then
# Complete source and destination keys
local IFS=$'\n'
COMPREPLY=( $( echo "$keys" | grep -i "^${cur//\\/\\\\}" ) )
fi
;;
delete)
if [[ $key_index -eq $COMP_CWORD ]]; then
# Complete key
local IFS=$'\n'
COMPREPLY=( $( echo "$keys" | grep -i "^${cur//\\/\\\\}" ) )
fi
;;
esac
return 0
}
complete -F _defaults -o default defaults
# This file is licensed under the BSD license, as follows:
#
# Copyright (c) 2006, Playhaus
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of the Playhaus nor the names of its contributors may be
# used to endorse or promote products derived from this software without
# specific prior written permission.
#
# This software is provided by the copyright holders and contributors "as is"
# and any express or implied warranties, including, but not limited to, the
# implied warranties of merchantability and fitness for a particular purpose are
# disclaimed. In no event shall the copyright owner or contributors be liable
# for any direct, indirect, incidental, special, exemplary, or consequential
# damages (including, but not limited to, procurement of substitute goods or
# services; loss of use, data, or profits; or business interruption) however
# caused and on any theory of liability, whether in contract, strict liability,
# or tort (including negligence or otherwise) arising in any way out of the use
# of this software, even if advised of the possibility of such damage.

View File

@ -39,5 +39,4 @@ done
if [[ "${_git_bash_completion_found}" == false ]]; then if [[ "${_git_bash_completion_found}" == false ]]; then
_log_warning "no completion files found - please try enabling the 'system' completion instead." _log_warning "no completion files found - please try enabling the 'system' completion instead."
fi fi
# shellcheck disable=SC2154 # ignore unknown
unset "${!_git_bash_completion@}" unset "${!_git_bash_completion@}"

View File

@ -1,4 +1,4 @@
# shellcheck shell=bash # shellcheck shell=bash
if _command_exists pipenv; then if _command_exists pipenv; then
eval "$(pipenv --completion)" eval "$(_PIPENV_COMPLETE=bash_source pipenv)"
fi fi

View File

@ -13,3 +13,4 @@ You should be familiar with them in order to fully utilize Bash-it.
search search
reload reload
doctor doctor
profile

View File

@ -0,0 +1,31 @@
.. _profile:
Bash-it Profile
---------------
Have you ever wanted to port your *Bash-it* configuration into another machine?
If you did, then ``bash-it profile`` is for you!
This command can save and load custom *"profile"* files, that can be later
used to load and recreate your configuration, in any machine you would like |:smile:|
When porting your configuration into a new machine, you just need to save your current profile, copy the resulting *"profile"* file, and load it in the other machine.
Example
^^^^^^^
.. code-block:: bash
# Saves your current profile
bash-it profile save my_profile
# Load the default profile, which is the one used in the default installation.
bash-it profile load default
# Do whatever you want:
# Disable stuff
bash-it disable ...
# Enable stuff
bash-it enable ...
# If you want to get back into your original configuration, you can do it easily
bash-it profile load my_profile

View File

@ -208,6 +208,8 @@ export BASH_IT_AUTOMATIC_RELOAD_AFTER_CONFIG_CHANGE=''
source "${BASH_IT}"/vendor/github.com/erichs/composure/composure.sh source "${BASH_IT}"/vendor/github.com/erichs/composure/composure.sh
# shellcheck source=./lib/utilities.bash # shellcheck source=./lib/utilities.bash
source "$BASH_IT/lib/utilities.bash" source "$BASH_IT/lib/utilities.bash"
# shellcheck source=./lib/log.bash
source "${BASH_IT}/lib/log.bash"
cite _about _param _example _group _author _version cite _about _param _example _group _author _version
# shellcheck source=./lib/helpers.bash # shellcheck source=./lib/helpers.bash
source "$BASH_IT/lib/helpers.bash" source "$BASH_IT/lib/helpers.bash"
@ -219,12 +221,7 @@ if [[ -n $interactive && -z "${silent}" ]]; then
done done
else else
echo "" echo ""
echo -e "\033[0;32mEnabling reasonable defaults\033[0m" _bash-it-profile-load "default"
_enable-completion bash-it
_enable-completion system
_enable-plugin base
_enable-plugin alias-completion
_enable-alias general
fi fi
echo "" echo ""

View File

@ -108,6 +108,7 @@ bash-it ()
example '$ bash-it version' example '$ bash-it version'
example '$ bash-it reload' example '$ bash-it reload'
example '$ bash-it restart' example '$ bash-it restart'
example '$ bash-it profile list|save|load|rm [profile_name]'
example '$ bash-it doctor errors|warnings|all' example '$ bash-it doctor errors|warnings|all'
typeset verb=${1:-} typeset verb=${1:-}
shift shift
@ -126,6 +127,8 @@ bash-it ()
func=_help-$component;; func=_help-$component;;
doctor) doctor)
func=_bash-it-doctor-$component;; func=_bash-it-doctor-$component;;
profile)
func=_bash-it-profile-$component;;
search) search)
_bash-it-search $component "$@" _bash-it-search $component "$@"
return;; return;;
@ -457,6 +460,172 @@ _bash-it-doctor-() {
_bash-it-doctor-all _bash-it-doctor-all
} }
_bash-it-profile-save() {
_about 'saves the current configuration to the "profile" directory'
_group 'lib'
local name=$1
while [ -z "$1" ]; do
read -r -e -p "Please enter the name of the profile to save: " name
case $name in
"")
echo -e "\033[91mPlease choose a name.\033[m"
;;
*)
break
;;
esac
done
local profile_path="${BASH_IT}/profiles/${name}.bash_it"
if [ -f "$profile_path" ]; then
echo -e "\033[0;33mProfile \"$name\" already exists.\033[m"
while true; do
read -r -e -n 1 -p "Would you like to overwrite existing profile? [y/N] " RESP
case $RESP in
[yY])
echo -e "\033[0;32mOverwriting profile \"$name\"...\033[m"
rm "$profile_path"
break
;;
[nN] | "")
echo -e "\033[91mAborting profile save...\033[m"
return 1
;;
*)
echo -e "\033[91mPlease choose y or n.\033[m"
;;
esac
done
fi
local something_exists
echo "# This file is auto generated by Bash-it. Do not edit manually!" > "$profile_path"
for subdirectory in "plugins" "completion" "aliases"; do
local component_exists=""
echo "Saving $subdirectory configuration..."
for f in "${BASH_IT}/$subdirectory/available/"*.bash; do
_bash-it-determine-component-status-from-path "$f"
if [ "$enabled" == "x" ]; then
if [ -z "$component_exists" ]; then
# This is the first component of this type, print the header
component_exists="yes"
something_exists="yes"
echo "" >> "$profile_path"
echo "# $subdirectory" >> "$profile_path"
fi
echo "$subdirectory $enabled_file_clean" >> "$profile_path"
fi
done
done
if [ -z "$something_exists" ]; then
echo "It seems like no configuration was enabled.."
echo "Make sure to double check that this is the wanted behavior."
fi
echo "All done!"
echo ""
echo "Profile location: $profile_path"
echo "Load the profile by invoking \"bash-it profile load $name\""
}
_bash-it-profile-load-parse-profile() {
_about 'Internal function used to parse the profile file'
_param '1: path to the profile file'
_param '2: dry run- only check integrity of the profile file'
_example '$ _bash-it-profile-load-parse-profile "profile.bash_it" "dry"'
local num=0
while read -r -a line; do
num=$((num + 1))
# Ignore comments and empty lines
[[ -z "${line[*]}" || "${line[*]}" =~ ^#.* ]] && continue
local enable_func="_enable-${line[0]}"
local subdirectory=${line[0]}
local component=${line[1]}
typeset to_enable=$(command ls "${BASH_IT}/$subdirectory/available/$component".*bash 2>/dev/null | head -1)
# Ignore botched lines
if [[ -z "$to_enable" ]]; then
echo -e "\033[91mBad line(#$num) in profile, aborting load...\033[m"
local bad="bad line"
break
fi
# Do not actually modify config on dry run
[[ -z $2 ]] || continue
# Actually enable the component
$enable_func "$component"
done < "$1"
# Make sure to propagate the error
[[ -z $bad ]]
}
_bash-it-profile-list() {
about 'lists all profiles from the "profiles" directory'
_group 'lib'
echo "Available profiles:"
for profile in "${BASH_IT}/profiles"/*.bash_it; do
profile="${profile##*/}"
echo "${profile/.bash_it/}"
done
}
_bash-it-profile-rm() {
about 'Removes a profile from the "profiles" directory'
_group 'lib'
local name="$1"
if [[ -z $name ]]; then
echo -e "\033[91mPlease specify profile name to remove...\033[m"
return 1
fi
# Users should not be allowed to delete the default profile
if [[ $name == "default" ]]; then
echo -e "\033[91mCan not remove the default profile...\033[m"
return 1
fi
local profile_path="${BASH_IT}/profiles/$name.bash_it"
if [[ ! -f "$profile_path" ]]; then
echo -e "\033[91mCould not find profile \"$name\"...\033[m"
return 1
fi
command rm "$profile_path"
echo "Removed profile \"$name\" successfully!"
}
_bash-it-profile-load() {
_about 'loads a configuration from the "profiles" directory'
_group 'lib'
local name="$1"
if [[ -z $name ]]; then
echo -e "\033[91mPlease specify profile name to load, not changing configuration...\033[m"
return 1
fi
local profile_path="${BASH_IT}/profiles/$name.bash_it"
if [[ ! -f "$profile_path" ]]; then
echo -e "\033[91mCould not find profile \"$name\", not changing configuration...\033[m"
return 1
fi
echo "Trying to parse profile \"$name\"..."
if _bash-it-profile-load-parse-profile "$profile_path" "dry"; then
echo "Profile \"$name\" parsed successfully!"
echo "Disabling current configuration..."
_disable-all
echo ""
echo "Enabling configuration based on profile..."
_bash-it-profile-load-parse-profile "$profile_path"
echo ""
echo "Profile \"$name\" enabled!"
fi
}
_bash-it-restart() { _bash-it-restart() {
_about 'restarts the shell in order to fully reload it' _about 'restarts the shell in order to fully reload it'
_group 'lib' _group 'lib'
@ -492,6 +661,25 @@ _bash-it-reload() {
popd &> /dev/null || return popd &> /dev/null || return
} }
_bash-it-determine-component-status-from-path ()
{
_about 'internal function used to process component name and check if its enabled'
_param '1: full path to available component file'
_example '$ _bash-it-determine-component-status-from-path "${BASH_IT}/plugins/available/git.plugin.bash'
# Check for both the old format without the load priority, and the extended format with the priority
declare enabled_files enabled_file
enabled_file="${f##*/}"
enabled_file_clean=$(echo "$enabled_file" | sed -e 's/\(.*\)\..*\.bash/\1/g')
enabled_files=$(sort <(compgen -G "${BASH_IT}/enabled/*$BASH_IT_LOAD_PRIORITY_SEPARATOR${enabled_file}") <(compgen -G "${BASH_IT}/$subdirectory/enabled/${enabled_file}") <(compgen -G "${BASH_IT}/$subdirectory/enabled/*$BASH_IT_LOAD_PRIORITY_SEPARATOR${enabled_file}") | wc -l)
if [ "$enabled_files" -gt 0 ]; then
enabled='x'
else
enabled=' '
fi
}
_bash-it-describe () _bash-it-describe ()
{ {
_about 'summarizes available bash_it components' _about 'summarizes available bash_it components'
@ -511,17 +699,8 @@ _bash-it-describe ()
printf "%-20s%-10s%s\n" "$column_header" 'Enabled?' 'Description' 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 do
# Check for both the old format without the load priority, and the extended format with the priority _bash-it-determine-component-status-from-path "$f"
declare enabled_files enabled_file printf "%-20s%-10s%s\n" "$enabled_file_clean" " [$enabled]" "$(cat $f | metafor about-$file_type)"
enabled_file="${f##*/}"
enabled_files=$(sort <(compgen -G "${BASH_IT}/enabled/*$BASH_IT_LOAD_PRIORITY_SEPARATOR${enabled_file}") <(compgen -G "${BASH_IT}/$subdirectory/enabled/${enabled_file}") <(compgen -G "${BASH_IT}/$subdirectory/enabled/*$BASH_IT_LOAD_PRIORITY_SEPARATOR${enabled_file}") | wc -l)
if [ $enabled_files -gt 0 ]; then
enabled='x'
else
enabled=' '
fi
printf "%-20s%-10s%s\n" "$(basename $f | sed -e 's/\(.*\)\..*\.bash/\1/g')" " [$enabled]" "$(cat $f | metafor about-$file_type)"
done done
printf '\n%s\n' "to enable $preposition $file_type, do:" 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" printf '%s\n' "$ bash-it enable $file_type <$file_type name> [$file_type name]... -or- $ bash-it enable $file_type all"
@ -540,6 +719,17 @@ _on-disable-callback()
_command_exists $callback && $callback _command_exists $callback && $callback
} }
_disable-all ()
{
_about 'disables all bash_it components'
_example '$ _disable-all'
_group 'lib'
_disable-plugin "all"
_disable-alias "all"
_disable-completion "all"
}
_disable-plugin () _disable-plugin ()
{ {
_about 'disables bash_it plugin' _about 'disables bash_it plugin'
@ -623,7 +813,11 @@ _disable-thing ()
_bash-it-clean-component-cache "${file_type}" _bash-it-clean-component-cache "${file_type}"
if [ "$file_entity" = "all" ]; then
printf '%s\n' "$file_entity $(_bash-it-pluralize-component "$file_type") disabled."
else
printf '%s\n' "$file_entity disabled." printf '%s\n' "$file_entity disabled."
fi
} }
_enable-plugin () _enable-plugin ()
@ -636,6 +830,12 @@ _enable-plugin ()
_enable-thing "plugins" "plugin" $1 $BASH_IT_LOAD_PRIORITY_DEFAULT_PLUGIN _enable-thing "plugins" "plugin" $1 $BASH_IT_LOAD_PRIORITY_DEFAULT_PLUGIN
} }
_enable-plugins ()
{
_about 'alias of _enable-plugin'
_enable-plugin "$@"
}
_enable-alias () _enable-alias ()
{ {
_about 'enables bash_it alias' _about 'enables bash_it alias'
@ -646,6 +846,12 @@ _enable-alias ()
_enable-thing "aliases" "alias" $1 $BASH_IT_LOAD_PRIORITY_DEFAULT_ALIAS _enable-thing "aliases" "alias" $1 $BASH_IT_LOAD_PRIORITY_DEFAULT_ALIAS
} }
_enable-aliases ()
{
_about 'alias of _enable-alias'
_enable-alias "$@"
}
_enable-completion () _enable-completion ()
{ {
_about 'enables bash_it completion' _about 'enables bash_it completion'
@ -802,6 +1008,17 @@ _help-plugins()
rm $grouplist 2> /dev/null rm $grouplist 2> /dev/null
} }
_help-profile () {
_about 'help message for profile command'
_group 'lib'
echo "Manages profiles of bash it."
echo "Use 'bash-it profile list' to see all available profiles."
echo "Use 'bash-it profile save foo' to save the current configuration into a profile named 'foo'."
echo "Use 'bash-it profile load foo' to load an existing profile named 'foo'."
echo "Use 'bash-it profile rm foo' to remove an existing profile named 'foo'."
}
_help-update () { _help-update () {
_about 'help message for update command' _about 'help message for update command'
_group 'lib' _group 'lib'

View File

@ -4,13 +4,11 @@ about-plugin 'Autojump configuration, see https://github.com/wting/autojump for
# Only supports the Homebrew variant, Debian and Arch at the moment. # Only supports the Homebrew variant, Debian and Arch at the moment.
# Feel free to provide a PR to support other install locations # Feel free to provide a PR to support other install locations
# shellcheck disable=1090 # shellcheck disable=SC1090
if _bash_it_homebrew_check && [[ -s "${BASH_IT_HOMEBREW_PREFIX}/etc/profile.d/autojump.sh" ]]; then if _bash_it_homebrew_check && [[ -s "${BASH_IT_HOMEBREW_PREFIX}/etc/profile.d/autojump.sh" ]]; then
source "${BASH_IT_HOMEBREW_PREFIX}/etc/profile.d/autojump.sh" source "${BASH_IT_HOMEBREW_PREFIX}/etc/profile.d/autojump.sh"
elif _command_exists dpkg && dpkg -s autojump &> /dev/null; then elif _command_exists dpkg && dpkg -s autojump &> /dev/null; then
# shellcheck disable=SC1090
source "$(dpkg-query -S autojump.sh | cut -d' ' -f2)" source "$(dpkg-query -S autojump.sh | cut -d' ' -f2)"
elif _command_exists pacman && pacman -Q autojump &> /dev/null; then elif _command_exists pacman && pacman -Q autojump &> /dev/null; then
# shellcheck disable=SC1090
source "$(pacman -Ql autojump | grep autojump.sh | cut -d' ' -f2)" source "$(pacman -Ql autojump | grep autojump.sh | cut -d' ' -f2)"
fi fi

View File

@ -103,5 +103,3 @@ R () {
} }
alias U='source ~/.dirs' # Update bookmark stack alias U='source ~/.dirs' # Update bookmark stack
# Set the Bash option so that no '$' is required when using the above facility
shopt -s cdable_vars

View File

@ -4,14 +4,15 @@
cite about-plugin cite about-plugin
about-plugin 'load fzf, if you are using it' about-plugin 'load fzf, if you are using it'
_command_exists fzf || return
if [ -r ~/.fzf.bash ] ; then if [ -r ~/.fzf.bash ] ; then
source ~/.fzf.bash source ~/.fzf.bash
elif [ -r "${XDG_CONFIG_HOME:-$HOME/.config}"/fzf/fzf.bash ] ; then elif [ -r "${XDG_CONFIG_HOME:-$HOME/.config}"/fzf/fzf.bash ] ; then
source "${XDG_CONFIG_HOME:-$HOME/.config}"/fzf/fzf.bash source "${XDG_CONFIG_HOME:-$HOME/.config}"/fzf/fzf.bash
fi fi
# No need to continue if the command is not present
_command_exists fzf || return
if [ -z ${FZF_DEFAULT_COMMAND+x} ] && _command_exists fd ; then if [ -z ${FZF_DEFAULT_COMMAND+x} ] && _command_exists fd ; then
export FZF_DEFAULT_COMMAND='fd --type f' export FZF_DEFAULT_COMMAND='fd --type f'
fi fi

View File

@ -1,4 +1,4 @@
cite about-plugin # shellcheck shell=bash
about-plugin 'Java and JAR helper functions' about-plugin 'Java and JAR helper functions'
function jar_manifest { function jar_manifest {
@ -7,5 +7,5 @@ function jar_manifest {
param '1: JAR file to extract the MANIFEST from' param '1: JAR file to extract the MANIFEST from'
example 'jar_manifest lib/foo.jar' example 'jar_manifest lib/foo.jar'
unzip -c $1 META-INF/MANIFEST.MF unzip -c "${1:?${FUNCNAME[0]}: JAR file must be specified}" META-INF/MANIFEST.MF
} }

View File

@ -1,268 +1,185 @@
# shellcheck shell=bash
cite about-plugin cite about-plugin
about-plugin 'manage your jekyll site' about-plugin 'manage your jekyll site'
editpost() { function editpost() {
about 'edit a post' about 'edit a post'
param '1: site directory' param '1: site directory'
group 'jekyll' group 'jekyll'
unset SITE local SITE site POST DATE TITLE POSTS
if [ -z "$1" ] local -i COUNTER=1 POST_TO_EDIT ret
then if [[ -z "${1:-}" ]]; then
echo "Error: no site specified." echo "Error: no site specified."
echo "The site is the name of the directory your project is in." echo "The site is the name of the directory your project is in."
return 1 return 1
fi fi
for site in ${SITES[@]} for site in "${SITES[@]:-}"; do
do if [[ "${site##*/}" == "$1" ]]; then
if [ "${site##*/}" = "$1" ] SITE="${site}"
then
SITE=$site
break break
fi fi
done done
if [ -z "$SITE" ] if [[ -z "${SITE:-}" ]]; then
then
echo "No such site." echo "No such site."
return 1 return 1
fi fi
builtin cd "$SITE/_posts" pushd "${SITE}/_posts" > /dev/null || return
COUNTER=1 for POST in *; do
NUMBER="$RANDOM" DATE="$(echo "${POST}" | grep -oE "[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}")"
TMPFILE="/tmp/editpost-$NUMBER" TITLE="$(grep -oE "title: (.+)" < "${POST}")"
TITLE="${TITLE/title: /}"
for POST in * echo "${COUNTER}) ${DATE} ${TITLE}"
do POSTS[COUNTER]="$POST"
DATE=`echo $POST | grep -oE "[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}"` COUNTER="$((COUNTER + 1))"
TITLE=`cat $POST | grep -oE "title: (.+)"` done > >(less)
TITLE=`echo $TITLE | sed 's/title: //'` read -rp "Number of post to edit: " POST_TO_EDIT
echo "$COUNTER) $DATE $TITLE" >> "$TMPFILE" "${JEKYLL_EDITOR:-${VISUAL:-${EDITOR:-${ALTERNATE_EDITOR:-nano}}}}" "${POSTS[POST_TO_EDIT]}"
POSTS[$COUNTER]=$POST ret="$?"
COUNTER=`expr $COUNTER + 1` popd > /dev/null || return "$ret"
done return "$ret"
less $TMPFILE
read -p "Number of post to edit: " POST_TO_EDIT
if [ -z "$JEKYLL_EDITOR" ]
then
nano "${POSTS[$POST_TO_EDIT]}"
else
"$JEKYLL_EDITOR" "${POSTS[$POST_TO_EDIT]}"
fi
} }
newpost() { function newpost() {
about 'create a new post' about 'create a new post'
param '1: site directory' param '1: site directory'
group 'jekyll' group 'jekyll'
unset SITE local SITE site FNAME_POST_TITLE FNAME YAML_DATE
if [ -z "$1" ] local JEKYLL_FORMATTING FNAME_DATE OPTIONS OPTION POST_TYPE POST_TITLE
then local -i loc=0 ret
if [[ -z "${1:-}" ]]; then
echo "Error: no site specified." echo "Error: no site specified."
echo "The site is the name of the directory your project is in." echo "The site is the name of the directory your project is in."
return 1 return 1
fi fi
if [ -z "$SITE" ] if [[ -z "${SITE}" ]]; then
then
echo "No such site." echo "No such site."
return 1 return 1
fi fi
loc=0 for site in "${SITES[@]}"; do
if [[ "${site##*/}" == "$1" ]]; then
for site in ${SITES[@]} SITE="$site"
do JEKYLL_FORMATTING="${MARKUPS[loc]}"
if [ "${site##*/}" = "$1" ]
then
SITE=$site
JEKYLL_FORMATTING=${MARKUPS[$loc]}
break break
fi fi
loc=$(($loc+1)) loc=$((loc + 1))
done done
# 'builtin cd' into the local jekyll root # Change directory into the local jekyll root
pushd "${SITE}/_posts" > /dev/null || return
builtin cd "$SITE/_posts"
# Get the date for the new post's filename # Get the date for the new post's filename
FNAME_DATE="$(date "+%Y-%m-%d")"
FNAME_DATE=$(date "+%Y-%m-%d")
# If the user is using markdown or textile formatting, let them choose what type of post they want. Sort of like Tumblr. # If the user is using markdown or textile formatting, let them choose what type of post they want. Sort of like Tumblr.
OPTIONS=('Text' 'Quote' 'Image' 'Audio' 'Video' 'Link')
OPTIONS="Text Quote Image Audio Video Link" if [[ $JEKYLL_FORMATTING == "markdown" || $JEKYLL_FORMATTING == "textile" ]]; then
select OPTION in "${OPTIONS[@]}"; do
if [ $JEKYLL_FORMATTING = "markdown" -o $JEKYLL_FORMATTING = "textile" ] POST_TYPE="${OPTION}"
then
select OPTION in $OPTIONS
do
if [[ $OPTION = "Text" ]]
then
POST_TYPE="Text"
break break
fi
if [[ $OPTION = "Quote" ]]
then
POST_TYPE="Quote"
break
fi
if [[ $OPTION = "Image" ]]
then
POST_TYPE="Image"
break
fi
if [[ $OPTION = "Audio" ]]
then
POST_TYPE="Audio"
break
fi
if [[ $OPTION = "Video" ]]
then
POST_TYPE="Video"
break
fi
if [[ $OPTION = "Link" ]]
then
POST_TYPE="Link"
break
fi
done done
fi fi
# Get the title for the new post # Get the title for the new post
read -rp "Enter title of the new post: " POST_TITLE
read -p "Enter title of the new post: " POST_TITLE
# Convert the spaces in the title to hyphens for use in the filename # Convert the spaces in the title to hyphens for use in the filename
FNAME_POST_TITLE="${POST_TITLE/ /-}"
FNAME_POST_TITLE=`echo $POST_TITLE | tr ' ' "-"`
# Now, put it all together for the full filename # Now, put it all together for the full filename
FNAME="$FNAME_DATE-$FNAME_POST_TITLE.$JEKYLL_FORMATTING" FNAME="$FNAME_DATE-$FNAME_POST_TITLE.$JEKYLL_FORMATTING"
# And, finally, create the actual post file. But we're not done yet... # And, finally, create the actual post file. But we're not done yet...
{
touch "$FNAME"
# Write a little stuff to the file for the YAML Front Matter # Write a little stuff to the file for the YAML Front Matter
echo "---"
echo "---" >> $FNAME # Now we have to get the date, again. But this time for in the header (YAML Front Matter) of the file
YAML_DATE="$(date "+%B %d %Y %X")"
# Now we have to get the date, again. But this time for in the header (YAML Front Matter) of
# the file
YAML_DATE=$(date "+%B %d %Y %X")
# Echo the YAML Formatted date to the post file # Echo the YAML Formatted date to the post file
echo "date: $YAML_DATE"
echo "date: $YAML_DATE" >> $FNAME
# Echo the original post title to the YAML Front Matter header # Echo the original post title to the YAML Front Matter header
echo "title: $POST_TITLE"
echo "title: $POST_TITLE" >> $FNAME
# And, now, echo the "post" layout to the YAML Front Matter header # And, now, echo the "post" layout to the YAML Front Matter header
echo "layout: post"
echo "layout: post" >> $FNAME
# Close the YAML Front Matter Header # Close the YAML Front Matter Header
echo "---"
echo "---" >> $FNAME echo
echo >> $FNAME } > "${FNAME}"
# Generate template text based on the post type # Generate template text based on the post type
if [[ $JEKYLL_FORMATTING == "markdown" ]]; then
if [[ $JEKYLL_FORMATTING = "markdown" ]] case $POST_TYPE in
then "Text")
if [[ $POST_TYPE = "Text" ]]
then
true true
fi ;;
"Quote")
if [[ $POST_TYPE = "Quote" ]] echo "> Quote"
then echo
echo "> Quote" >> $FNAME echo "&mdash; Author"
echo >> $FNAME ;;
echo "&mdash; Author" >> $FNAME "Image")
fi echo "![Alternate Text](/path/to/image/or/url)"
;;
if [[ $POST_TYPE = "Image" ]] "Audio")
then echo "<html><audio src=\"/path/to/audio/file\" controls=\"controls\"></audio></html>"
echo "![Alternate Text](/path/to/image/or/url)" >> $FNAME ;;
fi "Video")
echo "<html><video src=\"/path/to/video\" controls=\"controls\"></video></html>"
if [[ $POST_TYPE = "Audio" ]] ;;
then "Link")
echo "<html><audio src=\"/path/to/audio/file\" controls=\"controls\"></audio></html>" >> $FNAME echo "[link][1]"
fi echo
echo "> Quote"
if [[ $POST_TYPE = "Video" ]] echo
then echo "[1]: url"
echo "<html><video src=\"/path/to/video\" controls=\"controls\"></video></html>" >> $FNAME ;;
fi esac
elif [[ $JEKYLL_FORMATTING == "textile" ]]; then
if [[ $POST_TYPE = "Link" ]] case $POST_TYPE in
then "Text")
echo "[link][1]" >> $FNAME
echo >> $FNAME
echo "> Quote" >> $FNAME
echo >> $FNAME
echo "[1]: url" >> $FNAME
fi
fi
if [[ $JEKYLL_FORMATTING = "textile" ]]
then
if [[ $POST_TYPE = "Text" ]]
then
true true
fi ;;
"Quote")
if [[ $POST_TYPE = "Quote" ]] echo "bq. Quote"
then echo
echo "bq. Quote" >> $FNAME echo "&mdash; Author"
echo >> $FNAME ;;
echo "&mdash; Author" >> $FNAME "Image")
fi echo "!url(alt text)"
;;
if [[ $POST_TYPE = "Image" ]] "Audio")
then echo "<html><audio src=\"/path/to/audio/file\" controls=\"controls\"></audio></html>"
echo "!url(alt text)" >> $FNAME ;;
fi "Video")
echo "<html><video src=\"/path/to/video\" controls=\"controls\"></video></html>"
if [[ $POST_TYPE = "Audio" ]] ;;
then "Link")
echo "<html><audio src=\"/path/to/audio/file\" controls=\"controls\"></audio></html>" >> $FNAME echo "\"Site\":url"
fi echo
echo "bq. Quote"
if [[ $POST_TYPE = "Video" ]] ;;
then esac
echo "<html><video src=\"/path/to/video\" controls=\"controls\"></video></html>" >> $FNAME fi >> "${FNAME}"
fi
if [[ $POST_TYPE = "Link" ]]
then
echo "\"Site\":url" >> $FNAME
echo >> $FNAME
echo "bq. Quote" >> $FNAME
fi
fi
# Open the file in your favorite editor # Open the file in your favorite editor
"${JEKYLL_EDITOR:-${VISUAL:-${EDITOR:-${ALTERNATE_EDITOR:-nano}}}}" "${FNAME}"
"$JEKYLL_EDITOR" $FNAME ret="$?"
popd > /dev/null || return "$ret"
return "$ret"
} }
function testsite() { function testsite() {
@ -270,31 +187,31 @@ function testsite() {
param '1: site directory' param '1: site directory'
group 'jekyll' group 'jekyll'
unset SITE local SITE site
if [ -z "$1" ] local -i ret
then if [[ -z "${1:-}" ]]; then
echo "Error: no site specified." echo "Error: no site specified."
echo "The site is the name of the directory your project is in." echo "The site is the name of the directory your project is in."
return 1 return 1
fi fi
for site in ${SITES[@]} for site in "${SITES[@]}"; do
do if [[ "${site##*/}" == "$1" ]]; then
if [ "${site##*/}" = "$1" ] SITE="$site"
then
SITE=$site
break break
fi fi
done done
if [ -z "$SITE" ] if [[ -z "${SITE}" ]]; then
then
echo "No such site." echo "No such site."
return 1 return 1
fi fi
builtin cd $SITE pushd "${SITE}" > /dev/null || return
jekyll --server --auto jekyll --server --auto
ret="$?"
popd > /dev/null || return "$ret"
return "$ret"
} }
function buildsite() { function buildsite() {
@ -302,32 +219,32 @@ function buildsite() {
param '1: site directory' param '1: site directory'
group 'jekyll' group 'jekyll'
unset SITE local SITE site
if [ -z "$1" ] local -i ret
then if [[ -z "${1:-}" ]]; then
echo "Error: no site specified." echo "Error: no site specified."
echo "The site is the name of the directory your project is in." echo "The site is the name of the directory your project is in."
return 1 return 1
fi fi
for site in ${SITES[@]} for site in "${SITES[@]}"; do
do if [[ "${site##*/}" == "$1" ]]; then
if [ "${site##*/}" = "$1" ] SITE="$site"
then
SITE=$site
break break
fi fi
done done
if [ -z "$SITE" ] if [[ -z "${SITE}" ]]; then
then
echo "No such site." echo "No such site."
return 1 return 1
fi fi
builtin cd $SITE pushd "${SITE}" > /dev/null || return
rm -rf _site rm -rf _site
jekyll --no-server jekyll --no-server
ret="$?"
popd > /dev/null || return "$ret"
return "$ret"
} }
function deploysite() { function deploysite() {
@ -335,33 +252,37 @@ function deploysite() {
param '1: site directory' param '1: site directory'
group 'jekyll' group 'jekyll'
unset SITE local SITE site REMOTE
if [ -z "$1" ] local -i loc=0 ret
then if [[ -z "${1:-}" ]]; then
echo "Error: no site specified." echo "Error: no site specified."
echo "The site is the name of the directory your project is in." echo "The site is the name of the directory your project is in."
return 1 return 1
fi fi
loc=0 for site in "${SITES[@]}"; do
if [[ "${site##*/}" == "$1" ]]; then
for site in ${SITES[@]} SITE="$site"
do # shellcheck disable=SC2153 # who knows
if [ "${site##*/}" = "$1" ] REMOTE="${REMOTES[loc]}"
then
SITE=$site
REMOTE=${REMOTES[$loc]}
break break
fi fi
loc=$(($loc+1)) loc=$((loc + 1))
done done
if [ -z "$SITE" ] if [[ -z "${SITE}" ]]; then
then
echo "No such site." echo "No such site."
return 1 return 1
fi fi
builtin cd $SITE pushd "${SITE}" > /dev/null || return
rsync -rz $REMOTE rsync -rz "${REMOTE?}"
ret="$?"
popd > /dev/null || return "$ret"
return "$ret"
} }
# Load the Jekyll config
if [[ -s "$HOME/.jekyllconfig" ]]; then
source "$HOME/.jekyllconfig"
fi

View File

@ -0,0 +1,12 @@
# This is the default profile of Bash-it
# plugins
plugins alias-completion
plugins base
# completion
completion bash-it
completion system
# aliases
aliases general

View File

@ -80,32 +80,42 @@ function __check_completion () {
@test "completion bash-it: show options" { @test "completion bash-it: show options" {
run __check_completion 'bash-it ' run __check_completion 'bash-it '
assert_line -n 0 "disable enable help migrate reload restart doctor search show update version" assert_line -n 0 "disable enable help migrate reload restart profile doctor search show update version"
} }
@test "completion bash-it: bash-ti - show options" { @test "completion bash-it: bash-ti - show options" {
run __check_completion 'bash-ti ' run __check_completion 'bash-ti '
assert_line -n 0 "disable enable help migrate reload restart doctor search show update version" assert_line -n 0 "disable enable help migrate reload restart profile doctor search show update version"
} }
@test "completion bash-it: shit - show options" { @test "completion bash-it: shit - show options" {
run __check_completion 'shit ' run __check_completion 'shit '
assert_line -n 0 "disable enable help migrate reload restart doctor search show update version" assert_line -n 0 "disable enable help migrate reload restart profile doctor search show update version"
} }
@test "completion bash-it: bashit - show options" { @test "completion bash-it: bashit - show options" {
run __check_completion 'bashit ' run __check_completion 'bashit '
assert_line -n 0 "disable enable help migrate reload restart doctor search show update version" assert_line -n 0 "disable enable help migrate reload restart profile doctor search show update version"
} }
@test "completion bash-it: batshit - show options" { @test "completion bash-it: batshit - show options" {
run __check_completion 'batshit ' run __check_completion 'batshit '
assert_line -n 0 "disable enable help migrate reload restart doctor search show update version" assert_line -n 0 "disable enable help migrate reload restart profile doctor search show update version"
} }
@test "completion bash-it: bash_it - show options" { @test "completion bash-it: bash_it - show options" {
run __check_completion 'bash_it ' run __check_completion 'bash_it '
assert_line -n 0 "disable enable help migrate reload restart doctor search show update version" assert_line -n 0 "disable enable help migrate reload restart profile doctor search show update version"
}
@test "completion bash-it: profile - show options" {
run __check_completion 'bash-it profile '
assert_line -n 0 "load save list rm"
}
@test "completion bash-it: profile load - show options" {
run __check_completion 'bash-it profile load '
assert_line -n 0 "default"
} }
@test "completion bash-it: show - show options" { @test "completion bash-it: show - show options" {

View File

@ -0,0 +1,12 @@
# plugins
plugins alias-completion
plugins base
# completion
completion bash-it
completion system
# aliases
aliases general
# Bad component
aliases bla

View File

@ -0,0 +1,12 @@
# plugins
plugins alias-completion
plugins base
# Bad type
pluugins alias-completion
# completion
completion bash-it
completion system
# aliases
aliases general

View File

@ -13,11 +13,24 @@ load ../../plugins/available/base.plugin
function local_setup { function local_setup {
setup_test_fixture setup_test_fixture
# Copy the test fixture to the Bash-it folder
if command -v rsync &> /dev/null; then
rsync -a "$BASH_IT/test/fixtures/bash_it/" "$BASH_IT/"
else
find "$BASH_IT/test/fixtures/bash_it" \
-mindepth 1 -maxdepth 1 \
-exec cp -r {} "$BASH_IT/" \;
fi
} }
# TODO Create global __is_enabled function # TODO Create global __is_enabled function
# TODO Create global __get_base_name function # TODO Create global __get_base_name function
# TODO Create global __get_enabled_name function # TODO Create global __get_enabled_name function
@test "bash-it: verify that the test fixture is available" {
assert_file_exist "$BASH_IT/profiles/test-bad-component.bash_it"
assert_file_exist "$BASH_IT/profiles/test-bad-type.bash_it"
}
@test "helpers: _command_exists function exists" { @test "helpers: _command_exists function exists" {
run type -a _command_exists &> /dev/null run type -a _command_exists &> /dev/null
@ -283,6 +296,149 @@ function local_setup {
assert_link_exist "$BASH_IT/enabled/225---nvm.plugin.bash" assert_link_exist "$BASH_IT/enabled/225---nvm.plugin.bash"
} }
@test "helper: profile load command sanity" {
run _bash-it-profile-load "default"
assert_link_exist "$BASH_IT/enabled/150---general.aliases.bash"
assert_link_exist "$BASH_IT/enabled/250---base.plugin.bash"
assert_link_exist "$BASH_IT/enabled/365---alias-completion.plugin.bash"
assert_link_exist "$BASH_IT/enabled/350---bash-it.completion.bash"
assert_link_exist "$BASH_IT/enabled/350---system.completion.bash"
}
@test "helper: profile save command sanity" {
run _enable-plugin "nvm"
run _bash-it-profile-save "test"
assert_line -n 0 "Saving plugins configuration..."
assert_line -n 1 "Saving completion configuration..."
assert_line -n 2 "Saving aliases configuration..."
assert_line -n 3 "All done!"
assert_file_exist "$BASH_IT/profiles/test.bash_it"
}
@test "helper: profile save creates valid file with only plugin enabled" {
run _enable-plugin "nvm"
run _bash-it-profile-save "test"
run cat "$BASH_IT/profiles/test.bash_it"
assert_line -n 0 "# This file is auto generated by Bash-it. Do not edit manually!"
assert_line -n 1 "# plugins"
assert_line -n 2 "plugins nvm"
}
@test "helper: profile save creates valid file with only completion enabled" {
run _enable-completion "bash-it"
run _bash-it-profile-save "test"
run cat "$BASH_IT/profiles/test.bash_it"
assert_line -n 0 "# This file is auto generated by Bash-it. Do not edit manually!"
assert_line -n 1 "# completion"
assert_line -n 2 "completion bash-it"
}
@test "helper: profile save creates valid file with only aliases enabled" {
run _enable-alias "general"
run _bash-it-profile-save "test"
run cat "$BASH_IT/profiles/test.bash_it"
assert_line -n 0 "# This file is auto generated by Bash-it. Do not edit manually!"
assert_line -n 1 "# aliases"
assert_line -n 2 "aliases general"
}
@test "helper: profile edge case, empty configuration" {
run _bash-it-profile-save "test"
assert_line -n 3 "It seems like no configuration was enabled.."
assert_line -n 4 "Make sure to double check that this is the wanted behavior."
run _enable-alias "general"
run _enable-plugin "base"
run _enable-plugin "alias-completion"
run _enable-completion "bash-it"
run _enable-completion "system"
run _bash-it-profile-load "test"
assert_link_not_exist "$BASH_IT/enabled/150---general.aliases.bash"
assert_link_not_exist "$BASH_IT/enabled/250---base.plugin.bash"
assert_link_not_exist "$BASH_IT/enabled/365---alias-completion.plugin.bash"
assert_link_not_exist "$BASH_IT/enabled/350---bash-it.completion.bash"
assert_link_not_exist "$BASH_IT/enabled/350---system.completion.bash"
}
@test "helper: profile save and load" {
run _enable-alias "general"
run _enable-plugin "base"
run _enable-plugin "alias-completion"
run _enable-completion "bash-it"
run _enable-completion "system"
run _bash-it-profile-save "test"
assert_success
run _disable-alias "general"
assert_link_not_exist "$BASH_IT/enabled/150---general.aliases.bash"
run _bash-it-profile-load "test"
assert_link_exist "$BASH_IT/enabled/150---general.aliases.bash"
}
@test "helper: profile load corrupted profile file: bad component" {
run _bash-it-profile-load "test-bad-component"
assert_line -n 1 -p "Bad line(#12) in profile, aborting load..."
}
@test "helper: profile load corrupted profile file: bad subdirectory" {
run _bash-it-profile-load "test-bad-type"
assert_line -n 1 -p "Bad line(#5) in profile, aborting load..."
}
@test "helper: profile rm sanity" {
run _bash-it-profile-save "test"
assert_file_exist "$BASH_IT/profiles/test.bash_it"
run _bash-it-profile-rm "test"
assert_line -n 0 "Removed profile \"test\" successfully!"
assert_file_not_exist "$BASH_IT/profiles/test.bash_it"
}
@test "helper: profile rm no params" {
run _bash-it-profile-rm ""
assert_line -n 0 -p "Please specify profile name to remove..."
}
@test "helper: profile load no params" {
run _bash-it-profile-load ""
assert_line -n 0 -p "Please specify profile name to load, not changing configuration..."
}
@test "helper: profile rm default" {
run _bash-it-profile-rm "default"
assert_line -n 0 -p "Can not remove the default profile..."
assert_file_exist "$BASH_IT/profiles/default.bash_it"
}
@test "helper: profile rm bad profile name" {
run _bash-it-profile-rm "notexisting"
assert_line -n 0 -p "Could not find profile \"notexisting\"..."
}
@test "helper: profile list sanity" {
run _bash-it-profile-list
assert_line -n 0 "Available profiles:"
assert_line -n 1 "default"
}
@test "helper: profile list more profiles" {
run _bash-it-profile-save "cactus"
run _bash-it-profile-save "another"
run _bash-it-profile-save "brother"
run _bash-it-profile-list
assert_line -n 0 "Available profiles:"
assert_line -n 4 "default"
assert_line -n 3 "cactus"
assert_line -n 1 "another"
assert_line -n 2 "brother"
}
@test "helpers: migrate plugins and completions that share the same name" { @test "helpers: migrate plugins and completions that share the same name" {
ln -s $BASH_IT/completion/available/dirs.completion.bash $BASH_IT/completion/enabled/350---dirs.completion.bash ln -s $BASH_IT/completion/available/dirs.completion.bash $BASH_IT/completion/enabled/350---dirs.completion.bash
assert_link_exist "$BASH_IT/completion/enabled/350---dirs.completion.bash" assert_link_exist "$BASH_IT/completion/enabled/350---dirs.completion.bash"

View File

@ -1,20 +1,21 @@
# shellcheck shell=bash # shellcheck shell=bash
# shellcheck disable=SC2034 # Expected behavior for themes. # shellcheck disable=SC2034 # Expected behavior for themes.
# shellcheck disable=SC2154 #TODO: fix these all.
SCM_THEME_PROMPT_DIRTY=" ${red}" SCM_THEME_PROMPT_DIRTY=" ${red?}"
SCM_THEME_PROMPT_CLEAN=" ${bold_green}" SCM_THEME_PROMPT_CLEAN=" ${bold_green?}"
SCM_THEME_PROMPT_PREFIX=" |" SCM_THEME_PROMPT_PREFIX=" |"
SCM_THEME_PROMPT_SUFFIX="${green}|" SCM_THEME_PROMPT_SUFFIX="${green?}|"
GIT_THEME_PROMPT_DIRTY=" ${red}" GIT_THEME_PROMPT_DIRTY=" ${red?}"
GIT_THEME_PROMPT_CLEAN=" ${bold_green}" GIT_THEME_PROMPT_CLEAN=" ${bold_green?}"
GIT_THEME_PROMPT_PREFIX=" ${green}|" GIT_THEME_PROMPT_PREFIX=" ${green?}|"
GIT_THEME_PROMPT_SUFFIX="${green}|" GIT_THEME_PROMPT_SUFFIX="${green?}|"
# Nicely formatted terminal prompt # Nicely formatted terminal prompt
function prompt_command() { function prompt_command() {
PS1="\n${bold_black}[${blue}\@${bold_black}]-${bold_black}[${green}\u${yellow}@${green}\h${bold_black}]-${bold_black}[${purple}\w${bold_black}]-$(scm_prompt_info)\n${reset_color}\$ " local scm_prompt_info
scm_prompt_info="$(scm_prompt_info)"
PS1="\n${bold_black?}[${blue?}\@${bold_black?}]-${bold_black?}[${green?}\u${yellow?}@${green?}\h${bold_black?}]-${bold_black?}[${purple?}\w${bold_black?}]-${scm_prompt_info?}\n${reset_color?}\$ "
} }
safe_append_prompt_command prompt_command safe_append_prompt_command prompt_command

View File

@ -1,16 +1,15 @@
# shellcheck shell=bash # shellcheck shell=bash
# shellcheck disable=SC2034 # Expected behavior for themes. # shellcheck disable=SC2034 # Expected behavior for themes.
# shellcheck disable=SC2154 #TODO: fix these all.
SCM_THEME_PROMPT_DIRTY=" ${red}" SCM_THEME_PROMPT_DIRTY=" ${red?}"
SCM_THEME_PROMPT_CLEAN=" ${bold_green}" SCM_THEME_PROMPT_CLEAN=" ${bold_green?}"
SCM_THEME_PROMPT_PREFIX=" |" SCM_THEME_PROMPT_PREFIX=" |"
SCM_THEME_PROMPT_SUFFIX="${green}|" SCM_THEME_PROMPT_SUFFIX="${green?}|"
GIT_THEME_PROMPT_DIRTY=" ${red}" GIT_THEME_PROMPT_DIRTY=" ${red?}"
GIT_THEME_PROMPT_CLEAN=" ${bold_green}" GIT_THEME_PROMPT_CLEAN=" ${bold_green?}"
GIT_THEME_PROMPT_PREFIX=" ${green}|" GIT_THEME_PROMPT_PREFIX=" ${green?}|"
GIT_THEME_PROMPT_SUFFIX="${green}|" GIT_THEME_PROMPT_SUFFIX="${green?}|"
RVM_THEME_PROMPT_PREFIX="|" RVM_THEME_PROMPT_PREFIX="|"
RVM_THEME_PROMPT_SUFFIX="|" RVM_THEME_PROMPT_SUFFIX="|"
@ -19,7 +18,10 @@ function prompt_command() {
#PS1="${bold_cyan}$(scm_char)${green}$(scm_prompt_info)${purple}$(ruby_version_prompt) ${yellow}\h ${reset_color}in ${green}\w ${reset_color}\n${green}→${reset_color} " #PS1="${bold_cyan}$(scm_char)${green}$(scm_prompt_info)${purple}$(ruby_version_prompt) ${yellow}\h ${reset_color}in ${green}\w ${reset_color}\n${green}→${reset_color} "
#PS1="\n${purple}\h: ${reset_color} ${green}\w\n${bold_cyan}$(scm_char)${green}$(scm_prompt_info) ${green}→${reset_color} " #PS1="\n${purple}\h: ${reset_color} ${green}\w\n${bold_cyan}$(scm_char)${green}$(scm_prompt_info) ${green}→${reset_color} "
#PS1="\n${cyan}\h: ${reset_color} ${yellow}\w\n${red}$(scm_char)${red}$(scm_prompt_info) ${green}→${reset_color} " #PS1="\n${cyan}\h: ${reset_color} ${yellow}\w\n${red}$(scm_char)${red}$(scm_prompt_info) ${green}→${reset_color} "
PS1="\n${cyan}\h:$(virtualenv_prompt) ${reset_color} ${yellow}\w ${green}$(scm_prompt_info)\n${reset_color}" local virtualenv_prompt scm_prompt_info
virtualenv_prompt="$(virtualenv_prompt)"
scm_prompt_info="$(scm_prompt_info)"
PS1="\n${cyan?}\h:${virtualenv_prompt} ${reset_color?} ${yellow?}\w ${green?}${scm_prompt_info}\n${reset_color?}"
} }
safe_append_prompt_command prompt_command safe_append_prompt_command prompt_command

View File

@ -1,24 +1,26 @@
# shellcheck shell=bash # shellcheck shell=bash
# shellcheck disable=SC2034 # Expected behavior for themes. # shellcheck disable=SC2034 # Expected behavior for themes.
# shellcheck disable=SC2154 #TODO: fix these all.
SCM_THEME_PROMPT_PREFIX=" ${yellow}" SCM_THEME_PROMPT_PREFIX=" ${yellow?}"
SCM_THEME_PROMPT_SUFFIX="${reset_color}" SCM_THEME_PROMPT_SUFFIX="${reset_color?}"
VIRTUALENV_THEME_PROMPT_PREFIX=" ${cyan}" VIRTUALENV_THEME_PROMPT_PREFIX=" ${cyan?}"
VIRTUALENV_THEME_PROMPT_SUFFIX="${reset_color}" VIRTUALENV_THEME_PROMPT_SUFFIX="${reset_color?}"
bold="\[\e[1m\]" bold="\[\e[1m\]"
if [ ${UID} -eq 0 ]; then if [[ ${UID} -eq 0 ]]; then
user_host="${bold_red}\u@\h${normal}${reset_color}" user_host="${bold_red?}\u@\h${normal?}${reset_color?}"
else else
user_host="${bold_green}\u@\h${normal}${reset_color}" user_host="${bold_green?}\u@\h${normal?}${reset_color?}"
fi fi
function prompt_command() { function prompt_command() {
local current_dir=" ${bold_blue}\w${normal}${reset_color}" local current_dir=" ${bold_blue?}\w${normal?}${reset_color?}"
PS1="╭─${user_host}${current_dir}$(virtualenv_prompt)$(scm_prompt_info)\n╰─${bold}\\$ ${normal}" local virtualenv_prompt scm_prompt_info
virtualenv_prompt="$(virtualenv_prompt)"
scm_prompt_info="$(scm_prompt_info)"
PS1="╭─${user_host?}${current_dir}${virtualenv_prompt}${scm_prompt_info}\n╰─${bold?}\\$ ${normal?}"
} }
safe_append_prompt_command prompt_command safe_append_prompt_command prompt_command

View File

@ -1,23 +1,23 @@
# shellcheck shell=bash # shellcheck shell=bash
SCM_THEME_PROMPT_PREFIX=${SCM_THEME_PROMPT_SUFFIX} SCM_THEME_PROMPT_PREFIX="${SCM_THEME_PROMPT_SUFFIX:-}"
SCM_THEME_PROMPT_DIRTY="${bold_red}${normal}" SCM_THEME_PROMPT_DIRTY="${bold_red?}${normal?}"
SCM_THEME_PROMPT_CLEAN="${bold_green}${normal}" SCM_THEME_PROMPT_CLEAN="${bold_green?}${normal?}"
SCM_GIT_CHAR="${green}±${normal}" SCM_GIT_CHAR="${green?}±${normal?}"
mark_prompt() { function mark_prompt() {
echo "${green}\$${normal}" echo "${green?}\$${normal?}"
} }
user_host_path_prompt() { function user_host_path_prompt() {
ps_user="${green}\u${normal}"; ps_user="${green?}\u${normal?}";
ps_host="${blue}\H${normal}"; ps_host="${blue?}\H${normal?}";
ps_path="${yellow}\w${normal}"; ps_path="${yellow?}\w${normal?}";
echo "$ps_user@$ps_host:$ps_path" echo "${ps_user?}@${ps_host?}:${ps_path?}"
} }
prompt() { function prompt() {
SCM_PROMPT_FORMAT=' [%s%s]' local SCM_PROMPT_FORMAT=' [%s%s]'
PS1="$(user_host_path_prompt)$(virtualenv_prompt)$(scm_prompt) $(mark_prompt) " PS1="$(user_host_path_prompt)$(virtualenv_prompt)$(scm_prompt) $(mark_prompt) "
} }

View File

@ -1,16 +1,15 @@
# shellcheck shell=bash # shellcheck shell=bash
# shellcheck disable=SC2034 # Expected behavior for themes. # shellcheck disable=SC2034 # Expected behavior for themes.
# shellcheck disable=SC2154 #TODO: fix these all.
# Define this here so it can be used by all of the Powerline themes # Define this here so it can be used by all of the Powerline themes
THEME_CHECK_SUDO=${THEME_CHECK_SUDO:=true} THEME_CHECK_SUDO=${THEME_CHECK_SUDO:=true}
function set_color() { function set_color() {
set +u local fg='' bg=''
if [[ "${1}" != "-" ]]; then if [[ "${1:-}" != "-" ]]; then
fg="38;5;${1}" fg="38;5;${1}"
fi fi
if [[ "${2}" != "-" ]]; then if [[ "${2:-}" != "-" ]]; then
bg="48;5;${2}" bg="48;5;${2}"
[[ -n "${fg}" ]] && bg=";${bg}" [[ -n "${fg}" ]] && bg=";${bg}"
fi fi
@ -99,14 +98,13 @@ function __powerline_k8s_namespace_prompt() {
} }
function __powerline_python_venv_prompt() { function __powerline_python_venv_prompt() {
set +u
local python_venv="" local python_venv=""
if [[ -n "${CONDA_DEFAULT_ENV}" ]]; then if [[ -n "${CONDA_DEFAULT_ENV:-}" ]]; then
python_venv="${CONDA_DEFAULT_ENV}" python_venv="${CONDA_DEFAULT_ENV}"
PYTHON_VENV_CHAR=${CONDA_PYTHON_VENV_CHAR} PYTHON_VENV_CHAR=${CONDA_PYTHON_VENV_CHAR}
elif [[ -n "${VIRTUAL_ENV}" ]]; then elif [[ -n "${VIRTUAL_ENV:-}" ]]; then
python_venv=$(basename "${VIRTUAL_ENV}") python_venv="${VIRTUAL_ENV##*/}"
fi fi
[[ -n "${python_venv}" ]] && echo "${PYTHON_VENV_CHAR}${python_venv}|${PYTHON_VENV_THEME_PROMPT_COLOR}" [[ -n "${python_venv}" ]] && echo "${PYTHON_VENV_CHAR}${python_venv}|${PYTHON_VENV_THEME_PROMPT_COLOR}"
@ -137,7 +135,7 @@ function __powerline_scm_prompt() {
elif [[ "${SCM_SVN_CHAR}" == "${SCM_CHAR}" ]]; then elif [[ "${SCM_SVN_CHAR}" == "${SCM_CHAR}" ]]; then
scm_prompt+="${SCM_CHAR}${SCM_BRANCH}${SCM_STATE}" scm_prompt+="${SCM_CHAR}${SCM_BRANCH}${SCM_STATE}"
fi fi
echo "$(eval "echo ${scm_prompt}")${scm}|${color}" echo "${scm_prompt?}${scm?}|${color}"
fi fi
} }
@ -243,12 +241,12 @@ function __powerline_left_segment() {
# Since the previous segment wasn't the last segment, add padding, if needed # Since the previous segment wasn't the last segment, add padding, if needed
# #
if [[ "${POWERLINE_COMPACT_BEFORE_SEPARATOR}" -eq 0 ]]; then if [[ "${POWERLINE_COMPACT_BEFORE_SEPARATOR}" -eq 0 ]]; then
LEFT_PROMPT+="$(set_color - "${LAST_SEGMENT_COLOR}") ${normal}" LEFT_PROMPT+="$(set_color - "${LAST_SEGMENT_COLOR}") ${normal?}"
fi fi
if [[ "${LAST_SEGMENT_COLOR}" -eq "${params[1]}" ]]; then if [[ "${LAST_SEGMENT_COLOR}" -eq "${params[1]}" ]]; then
LEFT_PROMPT+="$(set_color - "${LAST_SEGMENT_COLOR}")${POWERLINE_LEFT_SEPARATOR_SOFT}${normal}" LEFT_PROMPT+="$(set_color - "${LAST_SEGMENT_COLOR}")${POWERLINE_LEFT_SEPARATOR_SOFT}${normal?}"
else else
LEFT_PROMPT+="$(set_color "${LAST_SEGMENT_COLOR}" "${params[1]}")${POWERLINE_LEFT_SEPARATOR}${normal}" LEFT_PROMPT+="$(set_color "${LAST_SEGMENT_COLOR}" "${params[1]}")${POWERLINE_LEFT_SEPARATOR}${normal?}"
fi fi
fi fi
@ -258,7 +256,7 @@ function __powerline_left_segment() {
} }
function __powerline_left_last_segment_padding() { function __powerline_left_last_segment_padding() {
LEFT_PROMPT+="$(set_color - "${LAST_SEGMENT_COLOR}") ${normal}" LEFT_PROMPT+="$(set_color - "${LAST_SEGMENT_COLOR}") ${normal?}"
} }
function __powerline_last_status_prompt() { function __powerline_last_status_prompt() {
@ -285,9 +283,9 @@ function __powerline_prompt_command() {
[[ -n "${info}" ]] && __powerline_left_segment "${info}" [[ -n "${info}" ]] && __powerline_left_segment "${info}"
done done
[[ "${last_status}" -ne 0 ]] && __powerline_left_segment "$(__powerline_last_status_prompt ${last_status})" [[ "${last_status}" -ne 0 ]] && __powerline_left_segment "$(__powerline_last_status_prompt "${last_status}")"
if [[ -n "${LEFT_PROMPT}" ]] && [[ "${POWERLINE_COMPACT_AFTER_LAST_SEGMENT}" -eq 0 ]]; then if [[ -n "${LEFT_PROMPT}" ]] && [[ "${POWERLINE_COMPACT_AFTER_LAST_SEGMENT:-}" -eq 0 ]]; then
__powerline_left_last_segment_padding __powerline_left_last_segment_padding
fi fi
@ -296,11 +294,11 @@ function __powerline_prompt_command() {
prompt_color="$(set_color "${LAST_SEGMENT_COLOR}" -)" prompt_color="$(set_color "${LAST_SEGMENT_COLOR}" -)"
if [[ -n "${LEFT_PROMPT}" ]] && [[ -n "${POWERLINE_LEFT_LAST_SEGMENT_PROMPT_CHAR}" ]]; then if [[ -n "${LEFT_PROMPT}" ]] && [[ -n "${POWERLINE_LEFT_LAST_SEGMENT_PROMPT_CHAR}" ]]; then
LEFT_PROMPT+="$(set_color - "${LAST_SEGMENT_COLOR}")${POWERLINE_LEFT_LAST_SEGMENT_PROMPT_CHAR}" LEFT_PROMPT+="$(set_color - "${LAST_SEGMENT_COLOR}")${POWERLINE_LEFT_LAST_SEGMENT_PROMPT_CHAR}"
prompt_color="${normal}" prompt_color="${normal?}"
fi fi
[[ -n "${LEFT_PROMPT}" ]] && LEFT_PROMPT+="${prompt_color}${separator_char}${normal}" [[ -n "${LEFT_PROMPT}" ]] && LEFT_PROMPT+="${prompt_color}${separator_char}${normal?}"
if [[ "${POWERLINE_COMPACT_PROMPT}" -eq 0 ]]; then if [[ "${POWERLINE_COMPACT_PROMPT:-}" -eq 0 ]]; then
LEFT_PROMPT+=" " LEFT_PROMPT+=" "
fi fi

View File

@ -1,16 +1,15 @@
# shellcheck shell=bash # shellcheck shell=bash
# shellcheck disable=SC2034 # Expected behavior for themes. # shellcheck disable=SC2034 # Expected behavior for themes.
# shellcheck disable=SC2154 #TODO: fix these all.
# scm theming # scm theming
SCM_THEME_PROMPT_PREFIX="|" SCM_THEME_PROMPT_PREFIX="|"
SCM_THEME_PROMPT_SUFFIX="" SCM_THEME_PROMPT_SUFFIX=""
SCM_THEME_PROMPT_DIRTY=" ${bold_red}${normal}" SCM_THEME_PROMPT_DIRTY=" ${bold_red?}${normal?}"
SCM_THEME_PROMPT_CLEAN=" ${green}${normal}" SCM_THEME_PROMPT_CLEAN=" ${green?}${normal?}"
SCM_GIT_CHAR="${green}±${normal}" SCM_GIT_CHAR="${green?}±${normal?}"
SCM_SVN_CHAR="${bold_cyan}${normal}" SCM_SVN_CHAR="${bold_cyan?}${normal?}"
SCM_HG_CHAR="${bold_red}${normal}" SCM_HG_CHAR="${bold_red?}${normal?}"
VIRTUALENV_THEME_PROMPT_PREFIX="(" VIRTUALENV_THEME_PROMPT_PREFIX="("
VIRTUALENV_THEME_PROMPT_SUFFIX=")" VIRTUALENV_THEME_PROMPT_SUFFIX=")"
@ -20,20 +19,23 @@ VIRTUALENV_THEME_PROMPT_SUFFIX=")"
# export LSCOLORS="Gxfxcxdxbxegedabagacad" # export LSCOLORS="Gxfxcxdxbxegedabagacad"
# export LS_COLORS='no=00:fi=00:di=01;34:ln=00;36:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=41;33;01:ex=00;32:*.cmd=00;32:*.exe=01;32:*.com=01;32:*.bat=01;32:*.btm=01;32:*.dll=01;32:*.tar=00;31:*.tbz=00;31:*.tgz=00;31:*.rpm=00;31:*.deb=00;31:*.arj=00;31:*.taz=00;31:*.lzh=00;31:*.lzma=00;31:*.zip=00;31:*.zoo=00;31:*.z=00;31:*.Z=00;31:*.gz=00;31:*.bz2=00;31:*.tb2=00;31:*.tz2=00;31:*.tbz2=00;31:*.avi=01;35:*.bmp=01;35:*.fli=01;35:*.gif=01;35:*.jpg=01;35:*.jpeg=01;35:*.mng=01;35:*.mov=01;35:*.mpg=01;35:*.pcx=01;35:*.pbm=01;35:*.pgm=01;35:*.png=01;35:*.ppm=01;35:*.tga=01;35:*.tif=01;35:*.xbm=01;35:*.xpm=01;35:*.dl=01;35:*.gl=01;35:*.wmv=01;35:*.aiff=00;32:*.au=00;32:*.mid=00;32:*.mp3=00;32:*.ogg=00;32:*.voc=00;32:*.wav=00;32:' # export LS_COLORS='no=00:fi=00:di=01;34:ln=00;36:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=41;33;01:ex=00;32:*.cmd=00;32:*.exe=01;32:*.com=01;32:*.bat=01;32:*.btm=01;32:*.dll=01;32:*.tar=00;31:*.tbz=00;31:*.tgz=00;31:*.rpm=00;31:*.deb=00;31:*.arj=00;31:*.taz=00;31:*.lzh=00;31:*.lzma=00;31:*.zip=00;31:*.zoo=00;31:*.z=00;31:*.Z=00;31:*.gz=00;31:*.bz2=00;31:*.tb2=00;31:*.tz2=00;31:*.tbz2=00;31:*.avi=01;35:*.bmp=01;35:*.fli=01;35:*.gif=01;35:*.jpg=01;35:*.jpeg=01;35:*.mng=01;35:*.mov=01;35:*.mpg=01;35:*.pcx=01;35:*.pbm=01;35:*.pgm=01;35:*.png=01;35:*.ppm=01;35:*.tga=01;35:*.tif=01;35:*.xbm=01;35:*.xpm=01;35:*.dl=01;35:*.gl=01;35:*.wmv=01;35:*.aiff=00;32:*.au=00;32:*.mid=00;32:*.mp3=00;32:*.ogg=00;32:*.voc=00;32:*.wav=00;32:'
pure_prompt() { function pure_prompt() {
ps_host="${bold_blue}\h${normal}" local ps_host="${bold_blue?}\h${normal?}"
ps_user="${green}\u${normal}" local ps_user="${green?}\u${normal?}"
ps_user_mark="${green} $ ${normal}" local ps_user_mark="${green?} $ ${normal?}"
ps_root="${red}\u${red}" local ps_root="${red?}\u${red?}"
ps_root_mark="${red} # ${normal}" local ps_root_mark="${red?} # ${normal?}"
ps_path="${yellow}\w${normal}" local ps_path="${yellow?}\w${normal?}"
local virtualenv_prompt scm_prompt
virtualenv_prompt="$(virtualenv_prompt)"
scm_prompt="$(scm_prompt)"
# make it work # make it work
case $(id -u) in case "${EUID:-$UID}" in
0) 0)
PS1="$(virtualenv_prompt)$ps_root@$ps_host$(scm_prompt):$ps_path$ps_root_mark" PS1="${virtualenv_prompt}${ps_root}@${ps_host}${scm_prompt}:${ps_path}${ps_root_mark}"
;; ;;
*) *)
PS1="$(virtualenv_prompt)$ps_user@$ps_host$(scm_prompt):$ps_path$ps_user_mark" PS1="${virtualenv_prompt}${ps_user}@${ps_host}${scm_prompt}:${ps_path}${ps_user_mark}"
;; ;;
esac esac
} }

View File

@ -1,36 +1,44 @@
# shellcheck shell=bash # shellcheck shell=bash
# shellcheck disable=SC2034 # Expected behavior for themes. # shellcheck disable=SC2034 # Expected behavior for themes.
# shellcheck disable=SC2154 #TODO: fix these all.
SCM_THEME_PROMPT_DIRTY=" ${bold_red}${normal}" SCM_THEME_PROMPT_DIRTY=" ${bold_red?}${normal?}"
SCM_THEME_PROMPT_CLEAN=" ${bold_green}${normal}" SCM_THEME_PROMPT_CLEAN=" ${bold_green?}${normal?}"
SCM_THEME_PROMPT_PREFIX="${reset_color}( " SCM_THEME_PROMPT_PREFIX="${reset_color?}( "
SCM_THEME_PROMPT_SUFFIX=" ${reset_color})" SCM_THEME_PROMPT_SUFFIX=" ${reset_color?})"
GIT_THEME_PROMPT_DIRTY=" ${bold_red}${normal}" GIT_THEME_PROMPT_DIRTY=" ${bold_red?}${normal?}"
GIT_THEME_PROMPT_CLEAN=" ${bold_green}${normal}" GIT_THEME_PROMPT_CLEAN=" ${bold_green?}${normal?}"
GIT_THEME_PROMPT_PREFIX="${reset_color}( " GIT_THEME_PROMPT_PREFIX="${reset_color?}( "
GIT_THEME_PROMPT_SUFFIX=" ${reset_color})" GIT_THEME_PROMPT_SUFFIX=" ${reset_color?})"
STATUS_THEME_PROMPT_BAD="${bold_red}${reset_color}${normal} " STATUS_THEME_PROMPT_BAD="${bold_red?}${reset_color?}${normal?} "
STATUS_THEME_PROMPT_OK="${bold_green}${reset_color}${normal} " STATUS_THEME_PROMPT_OK="${bold_green?}${reset_color?}${normal?} "
PURITY_THEME_PROMPT_COLOR="${PURITY_THEME_PROMPT_COLOR:=$blue}" : "${PURITY_THEME_PROMPT_COLOR:=$blue}"
venv_prompt() { function venv_prompt() {
python_venv="" python_venv=""
# Detect python venv # Detect python venv
if [[ -n "${CONDA_DEFAULT_ENV}" ]]; then if [[ -n "${CONDA_DEFAULT_ENV:-}" ]]; then
python_venv="($PYTHON_VENV_CHAR${CONDA_DEFAULT_ENV}) " python_venv="(${PYTHON_VENV_CHAR}${CONDA_DEFAULT_ENV}) "
elif [[ -n "${VIRTUAL_ENV}" ]]; then elif [[ -n "${VIRTUAL_ENV}" ]]; then
python_venv="($PYTHON_VENV_CHAR$(basename "${VIRTUAL_ENV}")) " python_venv="(${PYTHON_VENV_CHAR}${VIRTUAL_ENV##*/}) "
fi fi
[[ -n "${python_venv}" ]] && echo "${python_venv}" [[ -n "${python_venv}" ]] && echo "${python_venv}"
} }
function prompt_command() { function prompt_command() {
local retval=$? ret_status local retval="$?" ret_status python_venv scm_prompt_info venv_prompt
ret_status="$([ $retval -eq 0 ] && echo -e "$STATUS_THEME_PROMPT_OK" || echo -e "$STATUS_THEME_PROMPT_BAD")" case "${retval}" in
PS1="\n${PURITY_THEME_PROMPT_COLOR}\w $(scm_prompt_info)\n${ret_status}$(venv_prompt)" 0)
ret_status="$STATUS_THEME_PROMPT_OK"
;;
*)
ret_status="$STATUS_THEME_PROMPT_BAD"
;;
esac
scm_prompt_info="$(scm_prompt_info)"
venv_prompt="$(venv_prompt)"
PS1="\n${PURITY_THEME_PROMPT_COLOR}\w ${scm_prompt_info}\n${ret_status}${venv_prompt}"
} }
safe_append_prompt_command prompt_command safe_append_prompt_command prompt_command

View File

@ -0,0 +1,40 @@
# EditorConfig is awesome: http://EditorConfig.org
[*]
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[**.md]
indent_style = space
indent_size = 2
trim_trailing_whitespace = false
[.git*]
indent_style = tab
[**.*sh]
indent_style = tab
indent_size = tab
shell_variant = bash
binary_next_line = true # like -bn
switch_case_indent = false # like -ci
space_redirects = true # like -sr
keep_padding = false # like -kp
function_next_line = true # like -fn
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[**.bats]
indent_style = tab
indent_size = tab
shell_variant = bash
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

View File

@ -0,0 +1,30 @@
BSD 3-Clause License
Copyright (c) 2006, Playhaus
Copyright (c) 2021, gaelicWizard.LLC
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,286 @@
# shellcheck shell=bash
# shellcheck disable=SC2207
#
# Bash command line completion for defaults
#
# Version 1.0 created by Jonathon Mah on 2006-11-08.
# Version 2.0 written by John Pell on 2021-09-11.
#
function matchpattern()
{
local PATTERN=${2:?$FUNCNAME: a pattern is required}
local SEP=${3:-|}
[[ -z "${PATTERN##*${SEP}${1}${SEP}*}" ]]
}
function _defaults_verbs()
{
local IFS=$'\n' # Treat only newlines as delimiters in string operations.
local LC_CTYPE='C' # Do not consider character set in string operations.
local LC_COLLATE='C' # Do not consider character set in pattern matching.
local cur="${COMP_WORDS[COMP_CWORD]}"
local prev="${COMP_WORDS[COMP_CWORD - 1]}"
COMPREPLY=()
case $COMP_CWORD in
1)
candidates=("${cmds// /$IFS}" "${host_opts[@]}")
;;
2 | 3)
candidates=("${cmds// /$IFS}")
;;
*)
return 1
;;
esac
COMPREPLY=($(compgen -W "${candidates[*]}" | grep -i "^${cur}"))
return 0
}
function _defaults_domains()
{
local IFS=$'\n' # Treat only newlines as delimiters in string operations.
local LC_CTYPE='C' # Do not consider character set in string operations.
local LC_COLLATE='C' # Do not consider character set in pattern matching.
local cur="${COMP_WORDS[COMP_CWORD]}"
local prev="${COMP_WORDS[COMP_CWORD - 1]}"
COMPREPLY=()
if [[ "$BASH_VERSINFO" -ge 4 ]]
then # Exponential performance issue on strings greater than about 10k.
local domains="$(defaults domains)"
local candidates=($(compgen -W "${domains//, /$IFS}" | grep -i "^${cur}"))
else
local domains="$(defaults domains | sed -e 's/, /^/g' | tr '^' '\n')"
local candidates=($(compgen -W "${domains}" | grep -i "^${cur}"))
fi
COMPREPLY=($(printf '%q\n' "${candidates[@]}"))
if grep -q "^$cur" <<< '-app'
then
COMPREPLY[${#COMPREPLY[@]}]="-app"
elif grep -q "^$cur" <<< '-g'
then
COMPREPLY[${#COMPREPLY[@]}]="-g"
fi
return 0
}
function _defaults()
{
local IFS=$'\n' # Treat only newlines as delimiters in string operations.
local LC_CTYPE='C' # Do not consider character set in string operations.
local LC_COLLATE='C' # Do not consider character set in pattern matching.
local cur="${COMP_WORDS[COMP_CWORD]}"
local prev="${COMP_WORDS[COMP_CWORD - 1]}"
COMPREPLY=()
local host_opts cmds cmd domain keys key_index candidates verbs value_types
host_opts=('-currentHost' '-host')
cmds=' delete domains export find help import read read-type rename write '
value_types=('-string' '-data' '-integer' '-float' '-boolean' '-date' '-array' '-array-add' '-dict' '-dict-add')
case $COMP_CWORD in
1)
_defaults_verbs
return "$?"
;;
2)
case $prev in
"-currentHost")
_defaults_verbs
;;
"-host")
_known_hosts -a
;;
*)
if matchpattern "$prev" "${cmds// /|}"
then
# TODO: not correct for verbs: domains, find, help
_defaults_domains
else
return 1 # verb is not recognized
fi
;;
esac
return "$?"
;;
3)
case ${COMP_WORDS[1]} in
"-currentHost")
_defaults_domains
return "$?"
;;
"-host")
_defaults_verbs
return "$?"
;;
esac
;;
4)
case ${COMP_WORDS[1]} in
"-host")
if matchpattern "$prev" "${cmds// /|}"
then
# TODO: not correct for verbs: domains, find, help
_defaults_domains
else
return 1 # verb is not recognized
fi
;;
esac
;;
esac
# Both a domain and command have been specified
case ${COMP_WORDS[1]} in
"-currentHost")
if matchpattern "${COMP_WORDS[2]}" "${cmds// /|}"
then
cmd="${COMP_WORDS[2]}"
domain="${COMP_WORDS[3]}"
key_index=4
if [[ "$domain" == "-app" ]]
then
if [[ $COMP_CWORD -eq 4 ]]
then
# Completing application name. Can't help here, sorry
return 0
fi
domain="-app ${COMP_WORDS[4]}"
key_index=5
fi
fi
;;
"-host")
if matchpattern "${COMP_WORDS[3]}" "${cmds// /|}"
then
cmd="${COMP_WORDS[3]}"
domain="${COMP_WORDS[4]}"
key_index=5
if [[ "$domain" == "-app" ]]
then
if [[ $COMP_CWORD -eq 5 ]]
then
# Completing application name. Can't help here, sorry
return 0
fi
domain="-app ${COMP_WORDS[5]}"
key_index=6
fi
fi
;;
*)
if matchpattern "${COMP_WORDS[1]}" "${cmds// /|}"
then
cmd="${COMP_WORDS[1]}"
domain="${COMP_WORDS[2]}"
key_index=3
if [[ "$domain" == "-app" ]]
then
if [[ $COMP_CWORD -eq 3 ]]
then
# Completing application name. Can't help here, sorry
return 0
fi
domain="-app ${COMP_WORDS[3]}"
key_index=4
fi
fi
;;
esac
keys=($(defaults read "$domain" 2> /dev/null | sed -n -e '/^ [^}) ]/p' | sed -e 's/^ \([^" ]\{1,\}\) = .*$/\1/g' -e 's/^ "\([^"]\{1,\}\)" = .*$/\1/g'))
case $cmd in
read | read-type)
# Complete key
if candidates=($(compgen -W "${keys[*]:-}" | grep -i "^${cur}"))
then
COMPREPLY=($(printf '%q\n' "${candidates[@]}"))
fi
;;
write)
if [[ $key_index -eq $COMP_CWORD ]]
then
# Complete key
if candidates=($(compgen -W "${keys[*]:-}" | grep -i "^${cur}"))
then
COMPREPLY=($(printf '%q\n' "${candidates[@]}"))
fi
elif [[ $((key_index + 1)) -eq $COMP_CWORD ]]
then
# Complete value type
local cur_type="$(defaults read-type "$domain" "${COMP_WORDS[key_index]}" 2> /dev/null | sed -e 's/^Type is \(.*\)/-\1/' -e's/dictionary/dict/' | grep "^$cur")"
if [[ $cur_type ]]
then
COMPREPLY=("$cur_type")
else
COMPREPLY=($(compgen -W "${value_types[*]}" -- "$cur"))
fi
elif [[ $((key_index + 2)) -eq $COMP_CWORD ]]
then
# Complete value
COMPREPLY=($(defaults read "$domain" "${COMP_WORDS[key_index]}" 2> /dev/null | grep -i "^${cur//\\/\\\\}"))
fi
;;
rename)
if [[ $key_index -eq $COMP_CWORD || $((key_index + 1)) -eq $COMP_CWORD ]]
then
# Complete source and destination keys
if candidates=($(compgen -W "${keys[*]:-}" | grep -i "^${cur}"))
then
COMPREPLY=($(printf '%q\n' "${candidates[@]}"))
fi
fi
;;
delete)
if [[ $key_index -eq $COMP_CWORD ]]
then
# Complete key
if candidates=($(compgen -W "${keys[*]:-}" | grep -i "^${cur}"))
then
COMPREPLY=($(printf '%q\n' "${candidates[@]}"))
fi
fi
;;
esac
return 0
}
complete -F _defaults -o default defaults
# This file is licensed under the BSD license, as follows:
#
# Copyright (c) 2006, Playhaus
# Copyright (c) 2021, gaelicWizard.LLC
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the names of the authors nor the names of its contributors may be
# used to endorse or promote products derived from this software without
# specific prior written permission.
#
# This software is provided by the copyright holders and contributors "as is"
# and any express or implied warranties, including, but not limited to, the
# implied warranties of merchantability and fitness for a particular purpose are
# disclaimed. In no event shall the copyright owner or contributors be liable
# for any direct, indirect, incidental, special, exemplary, or consequential
# damages (including, but not limited to, procurement of substitute goods or
# services; loss of use, data, or profits; or business interruption) however
# caused and on any theory of liability, whether in contract, strict liability,
# or tort (including negligence or otherwise) arising in any way out of the use
# of this software, even if advised of the possibility of such damage.

View File

@ -0,0 +1,184 @@
#!/usr/bin/env bats
load ../test_helper
function local_setup() {
load ../../completion/available/defaults.completion
function _known_hosts() { :; }
function defaults() { echo 'NSGlobalDomain, Bash It'; }
}
function __check_completion() {
# Get the parameters as a single value
COMP_LINE=$*
# Get the parameters as an array
eval set -- "$@"
COMP_WORDS=("$@")
# Index of the cursor in the line
COMP_POINT=${#COMP_LINE}
# Get the last character of the line that was entered
COMP_LAST=$((${COMP_POINT} - 1))
# If the last character was a space...
if [[ ${COMP_LINE:$COMP_LAST} = ' ' ]]; then
# ...then add an empty array item
COMP_WORDS+=('')
fi
# Word index of the last word
COMP_CWORD=$(( ${#COMP_WORDS[@]} - 1 ))
# Run the Bash-it completion function
_defaults
# Return the completion output
echo "${COMPREPLY[@]}"
}
@test "completion defaults: ensure that the _defaults function is available" {
type -a _defaults &> /dev/null
assert_success
}
@test "completion defaults: - show verbs and options" {
run __check_completion 'defaults '
assert_line -n 0 'delete domains export find help import read read-type rename write -currentHost -host'
}
@test "completion defaults: r* - show matching verbs" {
run __check_completion 'defaults r'
assert_line -n 0 'read read-type rename'
}
@test "completion defaults: R* - show matching verbs" {
run __check_completion 'defaults R'
assert_line -n 0 'read read-type rename'
}
@test "completion defaults: -* - show matching flags" {
run __check_completion 'defaults -'
assert_line -n 0 '-currentHost -host'
}
@test "completion defaults: -currentHost - show verbs" {
run __check_completion 'defaults -currentHost '
assert_line -n 0 'delete domains export find help import read read-type rename write'
}
@test "completion defaults: -host - show nothing" {
run __check_completion 'defaults -host '
assert_line -n 0 "$(_known_hosts -a)"
}
@test "completion defaults: -host some_computer_name - show verbs" {
run __check_completion 'defaults -host some_computer_name '
assert_line -n 0 'delete domains export find help import read read-type rename write'
}
@test "completion defaults: read - show all domains" {
run __check_completion 'defaults read '
assert_line -n 0 "NSGlobalDomain Bash\ It -app"
}
@test "completion defaults: read nsg* - show matching domains" {
run __check_completion 'defaults read nsg'
assert_line -n 0 "NSGlobalDomain"
}
@test "completion defaults: read NSG* - show matching domains" {
run __check_completion 'defaults read NSG'
assert_line -n 0 "NSGlobalDomain"
}
@test "completion defaults: read bash* - show matching domains" {
run __check_completion 'defaults read bash'
assert_line -n 0 "Bash\ It"
}
@test "completion defaults: read BASH* - show matching domains" {
run __check_completion 'defaults read BASH'
assert_line -n 0 "Bash\ It"
}
@test "completion defaults: read bash* - show matching domains (with spaces)" {
run __check_completion 'defaults read bash\ i'
assert_line -n 0 "Bash\ It"
}
@test "completion defaults: read BASH* - show matching domains (with spaces)" {
run __check_completion 'defaults read BASH\ I'
assert_line -n 0 "Bash\ It"
}
@test "completion defaults: -currentHost read - show all domains" {
run __check_completion 'defaults -currentHost read '
assert_line -n 0 "NSGlobalDomain Bash\ It -app"
}
@test "completion defaults: -currentHost read nsg* - show matching domains" {
run __check_completion 'defaults -currentHost read nsg'
assert_line -n 0 "NSGlobalDomain"
}
@test "completion defaults: -currentHost read NSG* - show matching domains" {
run __check_completion 'defaults -currentHost read NSG'
assert_line -n 0 "NSGlobalDomain"
}
@test "completion defaults: -currentHost read bash* - show matching domains" {
run __check_completion 'defaults -currentHost read bash'
assert_line -n 0 "Bash\ It"
}
@test "completion defaults: -currentHost read BASH* - show matching domains" {
run __check_completion 'defaults -currentHost read BASH'
assert_line -n 0 "Bash\ It"
}
@test "completion defaults: -currentHost read bash* - show matching domains (with spaces)" {
run __check_completion 'defaults -currentHost read bash\ i'
assert_line -n 0 "Bash\ It"
}
@test "completion defaults: -currentHost read BASH* - show matching domains (with spaces)" {
run __check_completion 'defaults -currentHost read BASH\ I'
assert_line -n 0 "Bash\ It"
}
@test "completion defaults: -host some.computer.name read - show all domains" {
run __check_completion 'defaults -host some.computer.name read '
assert_line -n 0 "NSGlobalDomain Bash\ It -app"
}
@test "completion defaults: -host some.computer.name read nsg* - show matching domains" {
run __check_completion 'defaults -host some.computer.name read nsg'
assert_line -n 0 "NSGlobalDomain"
}
@test "completion defaults: -host some.computer.name read NSG* - show matching domains" {
run __check_completion 'defaults -host some.computer.name read NSG'
assert_line -n 0 "NSGlobalDomain"
}
@test "completion defaults: -host some.computer.name read bash* - show matching domains" {
run __check_completion 'defaults -host some.computer.name read bash'
assert_line -n 0 "Bash\ It"
}
@test "completion defaults: -host some.computer.name read BASH* - show matching domains" {
run __check_completion 'defaults -host some.computer.name read BASH'
assert_line -n 0 "Bash\ It"
}
@test "completion defaults: -host some.computer.name read bash* - show matching domains (with spaces)" {
run __check_completion 'defaults -host some.computer.name read bash\ i'
assert_line -n 0 "Bash\ It"
}
@test "completion defaults: -host some.computer.name read BASH* - show matching domains (with spaces)" {
run __check_completion 'defaults -host some.computer.name read BASH\ I'
assert_line -n 0 "Bash\ It"
}

View File

@ -8,7 +8,7 @@
# Disable immediate `$PROMPT_COMMAND` modification # Disable immediate `$PROMPT_COMMAND` modification
__bp_delay_install="delayed" __bp_delay_install="delayed"
# shellcheck source=SCRIPTDIR/../github.com/rcaloras/bash-preexec # shellcheck source-path=SCRIPTDIR/../github.com/rcaloras/bash-preexec
source "${BASH_IT?}/vendor/github.com/rcaloras/bash-preexec/bash-preexec.sh" source "${BASH_IT?}/vendor/github.com/rcaloras/bash-preexec/bash-preexec.sh"
# Block damanaging user's `$HISTCONTROL` # Block damanaging user's `$HISTCONTROL`