Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 17 additions & 33 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,48 +36,32 @@ body:
Provide a link to a live example, or an unambiguous set of steps to reproduce this bug. Include code to reproduce, if relevant.
validations:
required: true
- type: input
attributes:
label: Bash-it version
placeholder: "How to get: bash-it version"
validations:
required: true
- type: input
attributes:
label: List of enabled plugins, themes and aliases
placeholder: "How to get: bash-it show plugins|themes|aliases (it is not a pipe)"
validations:
required: true
- type: input
attributes:
label: Bash version
placeholder: "How to get: bash --version"
validations:
required: true
- type: input
attributes:
label: Operating system and version
placeholder: "How to get: neofetch (or another command)"
validations:
required: true
- type: textarea
attributes:
label: "bash-it doctor output"
label: "Diagnostic Information"
description: >
**Please run `bash-it doctor` and paste the complete output below.**
This single command provides all the diagnostic information we need including:
bash-it version, enabled components, bash version, OS version, and configuration.
placeholder: "Run: bash-it doctor"
value: |
```
# How to get: bash-it doctor
# Paste the output of: bash-it doctor


```
validations:
required: false
required: true
- type: textarea
attributes:
label: Your ~/.bashrc
value: |
```bash
# How to get: cat ~/.bashrc
```
label: "Additional Context (Optional)"
description: >
Any additional information that might help diagnose the issue.
This could include specific error messages, relevant parts of your ~/.bashrc,
or other configuration details not captured by `bash-it doctor`.
placeholder: "Paste any additional relevant information here"
validations:
required: true
required: false
- type: textarea
attributes:
label: Notes
Expand Down
21 changes: 21 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Stop polluting your `~/bin` directory and your `.bashrc` file, fork/clone Bash-i
- [via Docker](https://bash-it.readthedocs.io/en/latest/installation/#install-using-docker)
- [Updating](https://bash-it.readthedocs.io/en/latest/installation/#updating)
- [Help](https://bash-it.readthedocs.io/en/latest/misc/#help-screens)
- [Diagnostics](#diagnostics)
- [Search](https://bash-it.readthedocs.io/en/latest/commands/search)
- [Syntax](https://bash-it.readthedocs.io/en/latest/commands/search/#syntax)
- [Searching with Negations](
Expand Down Expand Up @@ -54,10 +55,30 @@ If this is undesirable, you can create another file, by run the installer:
BASH_IT_CONFIG_FILE=path/to/my/custom/location.bash ~/.bash_it/install.sh
```

## Diagnostics

If you're experiencing issues with Bash-it or need to report a bug, use the built-in diagnostics tool:

```bash
bash-it doctor
```

This command provides a comprehensive summary including:
- Environment information (OS, Bash version)
- Bash-it version and update status
- Configuration file locations and how Bash-it is loaded
- List of enabled components (aliases, plugins, completions)

**When reporting bugs**, please include the full output of `bash-it doctor` in your issue report.

The doctor command can also help you update Bash-it - if you're behind the latest version and it's safe to update, you'll be prompted to merge the latest changes.

## Contributing

Please take a look at the [Contribution Guidelines](https://bash-it.readthedocs.io/en/latest/contributing) before reporting a bug or providing a new feature.

**When reporting bugs**, always run `bash-it doctor` and include its output in your issue report to help maintainers diagnose the problem quickly.

The [Development Guidelines](https://bash-it.readthedocs.io/en/latest/development) 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.

Expand Down
192 changes: 189 additions & 3 deletions lib/helpers.bash
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ function bash-it() {
example '$ bash-it reload'
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|summary'
local verb=${1:-}
shift
local component=${1:-}
Expand Down Expand Up @@ -414,11 +414,197 @@ function _bash-it-doctor-errors() {
_bash-it-doctor "${BASH_IT_LOG_LEVEL_ERROR?}"
}

function _bash-it-doctor-summary() {
_about 'shows a comprehensive diagnostic summary for bug reports'
_group 'lib'

local component_type enabled_count enabled_list f component_name

# Color definitions
local BOLD CYAN GREEN YELLOW RESET
BOLD=$(tput bold 2> /dev/null || echo "")
CYAN=$(tput setaf 6 2> /dev/null || echo "")
GREEN=$(tput setaf 2 2> /dev/null || echo "")
YELLOW=$(tput setaf 3 2> /dev/null || echo "")
RESET=$(tput sgr0 2> /dev/null || echo "")

echo "${BOLD}${CYAN}Bash-it Doctor Summary${RESET}"
echo "${CYAN}======================${RESET}"
echo ""

# Environment Information
echo "${BOLD}## Environment${RESET}"
echo "${GREEN}OS:${RESET} $(uname -s) $(uname -r)"
echo "${GREEN}Bash Version:${RESET} ${BASH_VERSION}"
echo "${GREEN}Bash-it Location:${RESET} ${BASH_IT}"

# Check which config file is used
local config_file
if [[ -n "${BASH_IT_BASHRC:-}" ]]; then
config_file="${BASH_IT_BASHRC}"
elif [[ -f "${HOME}/.bashrc" ]]; then
config_file="${HOME}/.bashrc"
elif [[ -f "${HOME}/.bash_profile" ]]; then
config_file="${HOME}/.bash_profile"
else
config_file="unknown"
fi
echo "${GREEN}Config File:${RESET} ${config_file}"
echo ""

# Bash-it Version Information
echo "${BOLD}## Bash-it Version${RESET}"
pushd "${BASH_IT}" > /dev/null 2>&1 || {
echo "Error: Cannot access Bash-it directory"
return 1
}

local current_commit current_tag commits_behind latest_tag commits_since_tag
current_commit="$(git rev-parse --short HEAD 2> /dev/null || echo 'unknown')"
current_tag="$(git describe --exact-match --tags 2> /dev/null || echo 'none')"

if [[ -z "${BASH_IT_REMOTE:-}" ]]; then
BASH_IT_REMOTE="origin"
fi

# Get version info relative to tags
latest_tag="$(git describe --tags --abbrev=0 2> /dev/null || echo 'none')"
commits_since_tag="$(git rev-list --count "${latest_tag}..HEAD" 2> /dev/null || echo '0')"

if [[ "${current_tag}" != "none" ]]; then
echo "${GREEN}Current Version:${RESET} ${current_tag} (${current_commit})"
elif [[ "${latest_tag}" != "none" && "${commits_since_tag}" != "0" ]]; then
echo "${GREEN}Current Version:${RESET} ${latest_tag} +${commits_since_tag} (${current_commit})"
else
echo "${GREEN}Current Commit:${RESET} ${current_commit}"
fi

# Check how far behind we are
git fetch "${BASH_IT_REMOTE}" --quiet 2> /dev/null
if [[ -z "${BASH_IT_DEVELOPMENT_BRANCH:-}" ]]; then
BASH_IT_DEVELOPMENT_BRANCH="master"
fi
commits_behind="$(git rev-list --count HEAD.."${BASH_IT_REMOTE}/${BASH_IT_DEVELOPMENT_BRANCH}" 2> /dev/null || echo 'unknown')"

if [[ "${commits_behind}" == "0" ]]; then
echo "${GREEN}Status:${RESET} Up to date with ${BASH_IT_REMOTE}/${BASH_IT_DEVELOPMENT_BRANCH} ✓"
elif [[ "${commits_behind}" != "unknown" ]]; then
echo "${YELLOW}Status:${RESET} ${commits_behind} commits behind ${BASH_IT_REMOTE}/${BASH_IT_DEVELOPMENT_BRANCH}"

# Offer to update if behind and it's safe to do so
local git_status untracked_files merge_base can_ff
git_status="$(git status --porcelain 2> /dev/null)"
untracked_files="$(echo "$git_status" | grep -c '^??' || true)"

# Check if we can fast-forward
merge_base="$(git merge-base HEAD "${BASH_IT_REMOTE}/${BASH_IT_DEVELOPMENT_BRANCH}" 2> /dev/null)"
can_ff=false
if [[ "$(git rev-parse HEAD 2> /dev/null)" == "$merge_base" ]]; then
can_ff=true
fi

# Only offer merge if:
# 1. No modified/staged files (untracked are OK)
# 2. Can fast-forward OR no untracked files that would conflict
if ! echo "$git_status" | grep -v '^??' -q; then
if [[ "$can_ff" == "true" ]] || [[ "$untracked_files" == "0" ]]; then
echo ""
echo "Would you like to update now? This will merge ${BASH_IT_REMOTE}/${BASH_IT_DEVELOPMENT_BRANCH} into your current branch."
read -r -p "Update? [y/N] " response
case "$response" in
[yY] | [yY][eE][sS])
echo "Updating bash-it..."
if git merge "${BASH_IT_REMOTE}/${BASH_IT_DEVELOPMENT_BRANCH}" --ff-only 2> /dev/null; then
echo "✓ Successfully updated to latest version!"
echo ""
echo "Please restart your shell or run: source ~/.bashrc"
else
echo "✗ Fast-forward merge failed. Please run 'bash-it update' for a guided update."
fi
;;
*)
echo "Skipping update. You can update later with: bash-it update"
;;
esac
else
echo ""
echo "Note: Cannot safely auto-update (untracked files may conflict). Use: bash-it update"
fi
else
echo ""
echo "Note: Cannot auto-update (uncommitted changes present). Use: bash-it update"
fi
fi

popd > /dev/null 2>&1 || true
echo ""

# Bash-it Loading Configuration
echo "${BOLD}## Bash-it Loading${RESET}"
local config_files_to_check=()
local config_file_path

# Check all common config files
for config_file_path in "${HOME}/.bashrc" "${HOME}/.bash_profile" "${HOME}/.profile"; do
[[ -f "$config_file_path" ]] && config_files_to_check+=("$config_file_path")
done

if [[ ${#config_files_to_check[@]} -gt 0 ]]; then
for config_file_path in "${config_files_to_check[@]}"; do
if grep -i "bash.it\|bash_it" "$config_file_path" > /dev/null 2>&1; then
echo "From ${config_file_path}:"
grep -n -i "bash.it\|bash_it" -B2 -A2 "$config_file_path" 2> /dev/null
echo ""
fi
done
else
echo "No config files found (.bashrc, .bash_profile, .profile)"
fi

# Enabled Components Summary
echo "${BOLD}## Enabled Components${RESET}"

# Process each component type
for component_type in aliases plugins completion; do
enabled_count=0
enabled_list=()

# Get singular form for display
local display_type="${component_type}"
if [[ "$component_type" == "aliases" ]]; then
display_type="Aliases"
elif [[ "$component_type" == "plugins" ]]; then
display_type="Plugins"
else
display_type="Completions"
fi

# Count and collect enabled components
for f in "${BASH_IT?}/$component_type/available"/*.*.bash; do
[[ -f "$f" ]] || continue
component_name="$(_bash-it-get-component-name-from-path "$f")"
if _bash-it-component-item-is-enabled "$f"; then
enabled_list+=("$component_name")
((enabled_count++))
fi
done

# Display the summary with colors
if [[ $enabled_count -eq 0 ]]; then
printf '%s%s%s (%s): %s\n' "$CYAN" "$display_type" "$RESET" "$enabled_count" "${YELLOW}none${RESET}"
else
printf '%s%s%s (%s): %s\n' "$CYAN" "$display_type" "$RESET" "$enabled_count" "${enabled_list[*]}"
fi
done
echo ""
echo "${YELLOW}Tip:${RESET} To copy this report: ${CYAN}bash-it doctor${RESET} | pbcopy (macOS) or xclip (Linux)"
}

function _bash-it-doctor-() {
_about 'default bash-it doctor behavior, behaves like bash-it doctor all'
_about 'default bash-it doctor behavior, shows component summary'
_group 'lib'

_bash-it-doctor-all
_bash-it-doctor-summary
}

function _bash-it-profile-save() {
Expand Down
Loading