An input line editor for line-oriented terminal applications.
Based off the bubbletea library.
| Feature | Charm textarea 1 |
libedit 2 /readline 3 |
Bubbline (this library) |
|---|---|---|---|
| Multi-line editor with both horizontal and vertical cursor navigation. | ✅ | ✅ | ✅ |
| Secondary prompt for multi-line input. | ✅ | ✅ | ✅ |
| Resizes vertically automatically as the input grows. | ❌ | ✅ | ✅ |
| Supports history navigation and search. | ❌ | ✅ | ✅ |
| Word navigation across input lines. | ❌ | ✅ | ✅ |
| Enter key conditionally ends the input. | ❌ | ✅ | ✅ |
| Tab completion callback. | ❌ | ✅ | ✅ |
| Fancy presentation of completions with menu navigation. | ❌ | ✅ 4 | ✅ |
| Intelligent input interruption with Ctrl+C. | ❌ | ✅ | ✅ |
| Ctrl+Z (suspend process), Ctrl+\ (send SIGQUIT to process e.g. to get stack dump). | ❌ | ✅ | ✅ |
| Uppercase/lowercase/capitalize next word, transpose characters. | ✅ | ✅ | ✅ |
| Inline help for key bindings. | ❌ | ❌ | ✅ |
| Toggle overwrite mode. | ❌ 5 | ❌ | ✅ |
| Key combination to reflow the text to fit within a specific width. | ❌ | ❌ | ✅ |
| Hide/show the prompt to simplify copy-paste from terminal. | ❌ | ❌ | ✅ |
| Debug mode for troubleshooting. | ❌ | ❌ | ✅ |
| Open with external editor. | ❌ | (✅) 6 | ✅ |
| Bracketed paste 7 | ❌ 8 | ✅ | ❌ 8 |
| Default keys | Description | Binding name |
|---|---|---|
| Ctrl+D | Terminate the input if the cursor is at the beginning of a line; delete character otherwise. | EndOfInput |
| Ctrl+C | Clear the input if non-empty, or interrupt input if already empty. | Interrupt |
| Tab | Run the AutoComplete callback if defined. |
AutoComplete |
| Alt+. | Hide/show the prompt (eases copy-paste from terminal). | HideShowPrompt |
| Ctrl+L | Clear the screen and re-display the current input. | Refresh |
| Ctrl+G | Abort the search if currently searching; no-op otherwise. | AbortSearch |
| Ctrl+R | Start searching; or previous search match if already searching. | SearchBackward |
| Alt+P | Recall previous history entry. | HistoryPrevious |
| Alt+N | Recall next history entry. | HistoryNext |
| Enter, Ctrl+M | Enter a new line; or terminate input if CheckInputComplete returns true. |
InsertNewline |
| Alt+Enter, Alt+Ctrl+M | Always complete the input; ignore input termination condition. | AlwaysComplete |
| Ctrl+O | Always insert a newline; ignore input termination condition. | AlwaysNewline |
| Ctrl+F, Right | Move one character to the right. | CharacterBackward |
| Ctrl+B, Left | Move one character to the left. | CharacterForward |
| Alt+F, Alt+Right, Ctrl+Right | Move cursor to the previous word. | WordForward |
| Alt+B, Alt+Left, Ctrl+Left | Move cursor to the next word. | WordBackward |
| Ctrl+A, Home | Move cursor to beginning of line. | LineNext |
| Ctrl+E, End | Move cursor to end of line. | LineEnd |
| Alt+<, Ctrl+Home | Move cursor to beginning of input. | MoveToBegin |
| Alt+>, Ctrl+End | Move cursor to end of input. | MoveToEnd |
| Ctrl+P, Up | Move cursor one line up, or to previous history entry if already on first line. | LinePrevious |
| Ctrl+N, Down | Move cursor one line down, or to next history entry if already on last line. | LineStart |
| Ctrl+T | Transpose the last two characters. | TransposeCharacterBackward |
| Alt+O, Insert | Toggle overwrite mode. | ToggleOverwriteMode |
| Alt+U | Make the next word uppercase. | UppercaseWordForward |
| Alt+L | Make the next word lowercase. | LowercaseWordForward |
| Alt+C | Capitalize the next word. | CapitalizeWordForward |
| Ctrl+K | Delete the line after the cursor. | DeleteAfterCursor |
| Ctrl+U | Delete the line before the cursor. | DeleteBeforeCursor |
| Backspace, Ctrl+H | Delete the character before the cursor. | DeleteCharacterBackward |
| Delete | Delete the character after the cursor. | DeleteCharacterForward |
| Ctrl+W, Alt+Backspace | Delete the word before the cursor. | DeleteWordBackward |
| Alt+D, Alt+Delete | Delete the word after the cursor. | DeleteWordForward |
| Ctrl+\ | Send SIGQUIT to process. | SignalQuit |
| Ctrl+Z | Send SIGTSTOP to process (suspend). | SignalTTYStop |
| Alt+? | Toggle display of keybindings. | MoreHelp |
| Alt+q | Reflow the current line. | ReflowLine |
| Alt+Shift+Q | Reflow the entire input. | ReflowAll |
| Alt+2, Alt+F2 | Edit with an external editor, as defined by env var EDITOR. (not enabled by default) | ExternalEdit |
| Ctrl+_, Ctrl+@ | Print debug information about the editor. (not enabled by default) | Debug |
package main
import (
"errors"
"fmt"
"io"
"log"
tea "github.com/charmbracelet/bubbletea"
"github.com/knz/bubbline"
)
func main() {
// Instantiate the widget.
m := bubbline.New()
for {
// Read a line of input using the widget.
val, err := m.GetLine()
// Handle the end of input.
if err != nil {
if err == io.EOF {
// No more input.
break
}
if errors.Is(err, bubbline.ErrInterrupted) {
// Entered Ctrl+C to cancel input.
fmt.Println("^C")
} else if errors.Is(err, bubbline.ErrTerminated) {
fmt.Println("terminated")
break
} else {
fmt.Println("error:", err)
}
continue
}
// Handle regular input.
fmt.Printf("\nYou have entered: %q\n", val)
m.AddHistory(val)
}
}See the examples subdirectory for more examples!
Footnotes
-
libedit/readline's completion menu is a single line of options with wraparound. ↩
-
Possible to configure via key binding macro. ↩
-
Pending https://github.com/charmbracelet/bubbletea/pull/397 and https://github.com/charmbracelet/bubbletea/pull/397 ↩ ↩2
