Enhance TUI: add paste event handling, integrate bracketed paste mode, and implement paste support in editing mode.
Fixes #20
This commit is contained in:
@@ -11,7 +11,7 @@ use tokio::sync::mpsc;
|
|||||||
use tokio_util::sync::CancellationToken;
|
use tokio_util::sync::CancellationToken;
|
||||||
|
|
||||||
use crossterm::{
|
use crossterm::{
|
||||||
event::{DisableMouseCapture, EnableMouseCapture},
|
event::{DisableMouseCapture, EnableMouseCapture, DisableBracketedPaste, EnableBracketedPaste},
|
||||||
execute,
|
execute,
|
||||||
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
|
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
|
||||||
};
|
};
|
||||||
@@ -57,7 +57,7 @@ async fn main() -> Result<()> {
|
|||||||
// Terminal setup
|
// Terminal setup
|
||||||
enable_raw_mode()?;
|
enable_raw_mode()?;
|
||||||
let mut stdout = io::stdout();
|
let mut stdout = io::stdout();
|
||||||
execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?;
|
execute!(stdout, EnterAlternateScreen, EnableMouseCapture, EnableBracketedPaste)?;
|
||||||
let backend = CrosstermBackend::new(stdout);
|
let backend = CrosstermBackend::new(stdout);
|
||||||
let mut terminal = Terminal::new(backend)?;
|
let mut terminal = Terminal::new(backend)?;
|
||||||
|
|
||||||
@@ -74,7 +74,8 @@ async fn main() -> Result<()> {
|
|||||||
execute!(
|
execute!(
|
||||||
terminal.backend_mut(),
|
terminal.backend_mut(),
|
||||||
LeaveAlternateScreen,
|
LeaveAlternateScreen,
|
||||||
DisableMouseCapture
|
DisableMouseCapture,
|
||||||
|
DisableBracketedPaste
|
||||||
)?;
|
)?;
|
||||||
terminal.show_cursor()?;
|
terminal.show_cursor()?;
|
||||||
|
|
||||||
|
|||||||
@@ -381,6 +381,24 @@ impl ChatApp {
|
|||||||
Event::Tick => {
|
Event::Tick => {
|
||||||
// Future: update streaming timers
|
// Future: update streaming timers
|
||||||
}
|
}
|
||||||
|
Event::Paste(text) => {
|
||||||
|
// Handle paste events - insert text directly without triggering sends
|
||||||
|
if matches!(self.mode, InputMode::Editing) {
|
||||||
|
// In editing mode, insert the pasted text directly into textarea
|
||||||
|
let lines: Vec<&str> = text.lines().collect();
|
||||||
|
for (i, line) in lines.iter().enumerate() {
|
||||||
|
for ch in line.chars() {
|
||||||
|
self.textarea.insert_char(ch);
|
||||||
|
}
|
||||||
|
// Insert newline between lines (but not after the last line)
|
||||||
|
if i < lines.len() - 1 {
|
||||||
|
self.textarea.insert_newline();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.sync_textarea_to_buffer();
|
||||||
|
}
|
||||||
|
// Ignore paste events in other modes
|
||||||
|
}
|
||||||
Event::Key(key) => match self.mode {
|
Event::Key(key) => match self.mode {
|
||||||
InputMode::Normal => {
|
InputMode::Normal => {
|
||||||
// Handle multi-key sequences first
|
// Handle multi-key sequences first
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ pub enum Event {
|
|||||||
/// Terminal resize event
|
/// Terminal resize event
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
Resize(u16, u16),
|
Resize(u16, u16),
|
||||||
|
/// Paste event
|
||||||
|
Paste(String),
|
||||||
/// Tick event for regular updates
|
/// Tick event for regular updates
|
||||||
Tick,
|
Tick,
|
||||||
}
|
}
|
||||||
@@ -60,6 +62,9 @@ impl EventHandler {
|
|||||||
crossterm::event::Event::Resize(width, height) => {
|
crossterm::event::Event::Resize(width, height) => {
|
||||||
let _ = self.sender.send(Event::Resize(width, height));
|
let _ = self.sender.send(Event::Resize(width, height));
|
||||||
}
|
}
|
||||||
|
crossterm::event::Event::Paste(text) => {
|
||||||
|
let _ = self.sender.send(Event::Paste(text));
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user