https://github.com/ali5ter/pfb
🤩 Pretty feedback for your bash scripts
https://github.com/ali5ter/pfb
ansi ansi-escape-sequences bash messages prompt shell terminal tui utility
Last synced: 3 months ago
JSON representation
🤩 Pretty feedback for your bash scripts
- Host: GitHub
- URL: https://github.com/ali5ter/pfb
- Owner: ali5ter
- License: mit
- Created: 2022-04-11T14:31:45.000Z (about 4 years ago)
- Default Branch: main
- Last Pushed: 2025-12-20T03:43:39.000Z (6 months ago)
- Last Synced: 2025-12-21T03:07:55.951Z (6 months ago)
- Topics: ansi, ansi-escape-sequences, bash, messages, prompt, shell, terminal, tui, utility
- Language: Shell
- Homepage:
- Size: 7.79 MB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# pfb
Pretty feedback for Bash scripts.
Lightweight • Dependency-free • Pleasant by default

## Usage
Use the functions in this script by sourcing it in your scripts, e.g.
`source [path_to]/pfb.sh`
An example of pretty feedback provided by pfb can be shown by running the following command.
`source ./pfb.sh && pfb test`
### Configuration
pfb can be configured using environment variables:
| Variable | Default | Description |
| :------- | :------ | :---------- |
| `PFB_SPINNER_STYLE` | `2` | Spinner style (0-17). Run `pfb test` to see all styles |
| `PFB_SPINNER_LABEL` | `wait` | Spinner/progress prefix label. Set to empty string to suppress the prefix |
| `PFB_DEFAULT_LOG_DIR` | `$HOME/logs` | Directory where command logs are stored |
| `PFB_DEFAULT_LOG` | `scripts` | Base name for log files (creates `$PFB_DEFAULT_LOG.log`) |
| `PFB_NON_INTERACTIVE` | (unset) | Set to `1` to auto-answer prompts with defaults (CI, cron, scripts) |
| `NO_COLOR` | (unset) | Disable colors (see [no-color.org](https://no-color.org)) |
| `PFB_NO_COLOR` | `0` | pfb-specific color disable (set to `1` to disable) |
| `PFB_FORCE_COLOR` | (unset) | Force colors even when not a TTY (must be set before sourcing) |
Example:
```bash
export PFB_SPINNER_STYLE=13
export PFB_DEFAULT_LOG_DIR="/var/log/myscripts"
export NO_COLOR=1 # Disable colors for accessibility
source ./pfb.sh
```
### Log levels

pfb provides regular log level feedback using the following command.
`pfb [info|warn|error|success] message`
### Headings

pfb provides headings with a leading icon and sub-headings for adding detail under the heading.
A heading is echoed by using the following pfb command.
`pfb heading message [icon]`
Subheadings can be echoed after headings using
`pfb subheading message`
Not really a heading but a formatted subheading indicating a suggestion...
`pfb suggestion message`
### Long running commands

pfb can provide feedback that a command is being processed using
`pfb spinner start message some_command`
You can also start a spinner manually and stop it later:
```bash
pfb spinner start message
pfb spinner stop
```
The prefix label defaults to `[wait]`. Use `PFB_SPINNER_LABEL` to customise it or set it to
empty to suppress the prefix entirely:
```bash
PFB_SPINNER_LABEL="deploy" pfb spinner start "Deploying to production..." deploy.sh
# [deploy] ⣾ Deploying to production...
PFB_SPINNER_LABEL="" pfb spinner start "Downloading..." 'curl ...'
# ⣾ Downloading...
```
This is usefully followed up with a pfb success log level message or a pfb answer message.
### Progress bar

For operations with a known completion percentage, use the determinate progress bar:
`pfb progress [message]`
Each call redraws on the same line. Follow the loop with a log-level message to signal
completion:
```bash
files=(*.log)
for i in "${!files[@]}"; do
process "${files[$i]}"
pfb progress $(( i + 1 )) ${#files[@]} "Processing files..."
done
pfb success "All files processed!"
```
The bar adapts to the terminal width and respects `PFB_SPINNER_LABEL` for the prefix
(including the empty-string no-prefix option). Colors degrade to ASCII `=` characters
when `NO_COLOR` is set:
```bash
# Color mode (default)
# [wait] ████████████░░░░░░░░░░░░░░░ 42% Downloading...
# No-color mode
# [wait] [============ ] 42% Downloading...
```
### Text input

Collect text input from the user with an optional default value:
`result=$(pfb input "prompt message" [default_value])`
Example:
```bash
name=$(pfb input "What's your name?" "Anonymous")
echo "Hello, $name!"
```
The default value is shown in brackets and used if the user presses enter without typing anything.
### Confirmation prompts

Ask the user a yes/no question and get the result as an exit code:
`pfb confirm "question" [yes|no]`
Returns exit code 0 for yes, 1 for no. Use left/right arrow keys, `y`/`n`, or enter to select.
The selected option is highlighted and the hint capitalises the current default (`Y/n` or `y/N`).
An optional second argument sets the default answer (default is `yes`):
```bash
pfb confirm "Delete all files?" no # Defaults to No
pfb confirm "Continue?" yes # Defaults to Yes (explicit)
```
Example:
```bash
if pfb confirm "Delete this file?"; then
rm file.txt
pfb success "File deleted"
else
pfb info "Cancelled"
fi
```
### Selection from a set of options

pfb provides a way to select from a list of options using the up/down keys using
`pfb select array_of_options`
Example:
```bash
options=("Option 1" "Option 2" "Option 3")
selected=$(pfb select "${options[@]}")
echo "You selected: ${options[$selected]}"
```
### Prompt and answer

For integrating with external tools like fzf, use the prompt/answer pattern:
`pfb prompt message`
The pfb answer message can be used to put a formatted answer after the prompt message.
`pfb answer message`
This pattern saves the cursor position after the prompt and restores it when displaying the answer, keeping everything on
one line. For simple text input, use `pfb input` instead.
## Helper functions and variables
Cursor helper functions and color variables are available **immediately after sourcing** `pfb.sh`
— no prior `pfb` call is required.
> **Note:** Color variables (`INFO_COLOR`, `BOLD`, `RESET`, etc.) are set to ANSI codes only when
> stdout is a TTY at source time. In CI or piped contexts, set `PFB_FORCE_COLOR=1` **before**
> sourcing `pfb.sh` to force colors.
pfb uses ANSI/VT100 Terminal Control Escape Sequences which you can use yourself:
| Function Name | Use |
| :------- | ------- |
| cursor_on | Turn on the cursor |
| cursor_off | Turn off the cursor |
| get_cursor_row | Echo the current row number of the cursor |
| get_cursor_col | Echo the current column number of the cursor |
| cursor_to row [column] | Move the cursor to a position |
| cursor_up | Move the cursor to the row above |
| cursor_down | Move the cursor to the row below |
| cursor_sol | Move the cursor to the start of the current line |
| erase_down | Remove all content from the cursor down |
| erase_up | Remove all content from the cursor up |
| erase_screen | Remove all content from the screen |
| erase_eol | Remove all content from the cursor to the end of the line |
| erase_sol | Remove all content from the cursor to the start of the line |
| erase_line | Remove all content on the current line |
| save_pos | Store the current position of the cursor |
| restore_pos | Restore the position of the cursor to the last saved position |
| rgb_fg r g b | Set foreground color using RGB values (0-255) |
| rgb_bg r g b | Set background color using RGB values (0-255) |
Examples of how these area used can be seen in the pfb script.
| Variable Name | Use |
| :------- | ------- |
| BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE | Basic 8-color foreground colors |
| BBLACK BRED BGREEN BYELLOW BBLUE BMAGENTA BCYAN BWHITE | Basic 8-color background colors |
| INFO_COLOR | Soft blue-cyan (RGB: 100, 180, 220) for info messages |
| WARN_COLOR | Warm amber (RGB: 255, 180, 80) for warnings |
| ERROR_COLOR | Clear red (RGB: 240, 90, 90) for errors |
| SUCCESS_COLOR | Fresh green (RGB: 90, 200, 120) for success |
| SPINNER_COLOR | Claude orange (RGB: 215, 119, 87) for spinners |
| PROMPT_COLOR | Bright cyan (RGB: 120, 220, 240) for prompts |
| BOLD DIM REV RESET | Display attributes |
Examples using these variables:
`printf "${BYELLOW}${RED}${BOLD}This is bold red text on a yellow background${RESET}"`
`echo "${REV}This is reversed text${RESET}"`
`printf "${INFO_COLOR}Informational message${RESET}\n"`
`printf "${SUCCESS_COLOR}Success message${RESET}\n"`
Examples using RGB color functions:
`printf "$(rgb_fg 215 119 87)Orange text${RESET}\n"`
`printf "$(rgb_bg 50 150 50)Green background${RESET}\n"`
`printf "$(rgb_fg 255 100 200)$(rgb_bg 50 50 100)Custom colors${RESET}\n"`
## Comparison with gum
[gum](https://github.com/charmbracelet/gum) is a more comprehensive TUI toolkit that offers similar functionality with
additional components like file browsers, tables, pagers, and advanced text filtering.
**When to use pfb:**
- Zero dependencies - just source a single bash file (~10KB)
- Maximum portability (works anywhere with bash 4.0+)
- No external binary installation required
- Direct function calls (no process spawning overhead)
- Basic terminal feedback is sufficient for your needs
**When to use gum:**
- Need advanced components (file browser, tables, fuzzy filtering, pagers)
- Building sophisticated interactive scripts
- Prefer standalone binaries over sourced libraries
- Want extensive styling options via CLI flags
pfb occupies the lightweight, dependency-free niche — ideal for scripts you distribute or run in constrained
environments where installing external tools adds friction.