Chris Green <
cl@isbd.net> wrote or quoted:
Are there any packages that offer this sort of thing? I'd prefer ones
from the Debian repositories but that's not absolutely necessary.
So, in my humble opinion, it's a no-brainer to split this into two
camps and draw a line between Linux and Windows.
On Linux, you're going to wanna roll with curses. See [1] below.
For Windows, whip up your own terminal using tkinter (Yeah,
tkinter's a GUI library, no doubt! But in this case, it's just
being used to mimic a terminal.) as your secret sauce. See [2].
If that's too tied to specific systems for your taste,
why not cook up a library that smooths out those wrinkles?
The following drafts still contain bugs, but might convey
the idea.
[1]
import curses
def main(stdscr):
# Clear screen and hide cursor
stdscr.clear()
curses.curs_set(1)
# Display prompt
stdscr.addstr(0, 0, "Color? ")
# Pre-fill with "red"
default_text = "red"
stdscr.addstr(0, 7, default_text)
curses.echo() # Enable echo of characters
curses.cbreak() # React to keys instantly without Enter key
# Initialize cursor position
cursor_x = 7 + len(default_text)
current_text = default_text
while True:
stdscr.move(0, cursor_x)
ch = stdscr.getch()
if ch == ord('\n'): # Enter key
break
elif ch in (curses.KEY_BACKSPACE, 127): # Backspace
if cursor_x > 7:
cursor_x -= 1
current_text = current_text[:cursor_x-7] + current_text[cursor_x-6:]
stdscr.delch(0, cursor_x)
elif ch == curses.KEY_LEFT:
if cursor_x > 7:
cursor_x -= 1
elif ch == curses.KEY_RIGHT:
if cursor_x < 7 + len(current_text):
cursor_x += 1
elif 32 <= ch <= 126: # Printable characters
current_text = current_text[:cursor_x-7] + chr(ch) + current_text[cursor_x-7:]
stdscr.insch(0, cursor_x, ch)
cursor_x += 1
stdscr.refresh()
# Clear screen
stdscr.clear()
# Display result
stdscr.addstr(0, 0, f"You entered: {current_text}")
stdscr.refresh()
stdscr.getch()
if __name__ == "__main__":
curses.wrapper(main)
[2]
import tkinter as tk
from tkinter import simpledialog
class ColorQueryApp:
def __init__(self, master):
self.master = master
master.title("Color Query")
# Create the Text widget
self.text_field = tk.Text(master, height=10, width=40)
self.text_field.pack(padx=10, pady=10)
# Create a button to add new color queries
self.add_button = tk.Button(master, text="Add Color Query", command=self.add_color_query)
self.add_button.pack(pady=5)
# Bind the Return key event
self.text_field.bind('<Return>', self.show_color_dialog)
def add_color_query(self):
# Insert a new line if the Text widget is not empty
if self.text_field.index('end-1c') != '1.0':
self.text_field.insert('end', '\n')
# Insert the new color query line
query_line = "Color? red"
self.text_field.insert('end', query_line)
# Move the cursor to the end of the new line
self.text_field.mark_set('insert', f'{self.text_field.index("end-1c")}')
# Bind the key events
self.text_field.bind('<Key>', self.check_editing)
def check_editing(self, event):
# Allow all keystrokes if cursor is in editable area
if self.text_field.compare('insert', '>=', 'insert linestart+7c'):
return
# Prevent editing in the "Color? " area
if event.keysym in ['BackSpace', 'Delete'] or len(event.char) > 0:
return 'break'
def show_color_dialog(self, event):
# Get the current line
current_line = self.text_field.get("insert linestart", "insert lineend")
# Extract the color
color = current_line[7:].strip()
# Show a dialog with the entered color
simpledialog.messagebox.showinfo("Entered Color", f"You entered: {color}")
# Prevent the default newline behavior
return 'break'
root = tk.Tk()
app = ColorQueryApp(root)
root.mainloop()