如何实现命令行中输入内容显示在输入行上方的聊天式输出?
Hey there! Great question about building that chat-style command-line output. Your current approach works, but there are a few more elegant ways to get that exact behavior where your input shows up above the prompt. Let's break down three solid alternatives:
This is my go-to method for clean, flicker-free CLI interfaces. ANSI escape codes let you control the cursor position directly, so you can insert new messages above the separator without redrawing the entire screen.
Here's how to implement it:
username = "Tim" def print_chat_message(message) puts message end # Initialize the interface puts "-" * 30 print "What do you want to say? > " loop do input = gets.chomp break if input.downcase == "exit" # Add a way to quit # Step 1: Clear the current prompt line to avoid leftover text print "\e[K" # Step 2: Move cursor up 1 line to the separator print "\e[1A" # Step 3: Jump to the start of that line print "\e[0G" # Step 4: Print the new chat message above the separator print_chat_message("#{username}: #{input}") # Step 5: Re-print the separator and prompt puts "-" * 30 print "What do you want to say? > " end
How it works:
\e[K: Clears the current line (so old prompt text doesn't linger)\e[1A: Moves the cursor up 1 line to the separator\e[0G: Jumps to the start of the line, letting us print the new message above the separator- We re-print the separator and prompt to reset the interface, with the cursor back in the input position
If you don't mind a slight screen flicker, this method is dead simple. We maintain a history of chat messages, then clear the entire screen and re-draw everything each time the user sends a message.
username = "Tim" chat_history = [] def clear_terminal # Works on macOS/Linux and Windows system("clear") || system("cls") end loop do # Clear the screen first clear_terminal # Print all past messages chat_history.each { |msg| puts msg } # Print the separator puts "-" * 30 # Get user input print "What do you want to say? > " input = gets.chomp break if input.downcase == "exit" # Add the new message to history chat_history << "#{username}: #{input}" end
Pros & Cons:
- Pros: Super easy to write and debug, no need to learn ANSI codes
- Cons: Screen flickers each time you send a message, which might be distracting for longer chats
Ruby's built-in readline library adds powerful features like input history (press up arrow to see past messages) and line editing, while still letting you control the output layout.
require 'readline' username = "Tim" chat_history = [] # Set the default prompt Readline.prompt = "What do you want to say? > " loop do # Read input with history support (the `true` saves it to history) input = Readline.readline(nil, true) break if input.nil? || input.downcase == "exit" # Add the message to our chat history chat_history << "#{username}: #{input}" # Clear and re-draw the interface system("clear") || system("cls") chat_history.each { |msg| puts msg } puts "-" * 30 # Reset the prompt after clearing the screen Readline.prompt = "What do you want to say? > " end
Why use this?
- Built-in input history makes it easy for users to re-send or edit past messages
- Handles line editing (like using left/right arrows to fix typos) automatically
- More stable than manual
getsfor complex CLI interactions
Each method has its sweet spot: ANSI sequences give you the smoothest experience, clear-redraw is perfect for quick prototypes, and readline is ideal if you want to build a more polished CLI tool.
内容的提问来源于stack exchange,提问作者Tim Tenb

