import curses def main(stdscr): curses.curs_set(1) stdscr.clear() stdscr.refresh() text = [] row = 0 while True: stdscr.move(row, 0) stdscr.clrtoeol() stdscr.addstr(row, 0, ''.join(text)) stdscr.refresh() ch = stdscr.getch() if ch == 27: # ESCキーで終了 break elif ch == 10: # Enter text.append('\n') row += 1 elif ch == 127 or ch == curses.KEY_BACKSPACE: if text: text.pop() if text[-1] == '\n': row -= 1 else: text.append(chr(ch)) with open("output.txt", "w") as f: f.write(''.join(text)) curses.wrapper(main)
Rustで書くと
use crossterm::{ cursor, event::{read, Event, KeyCode}, terminal::{enable_raw_mode, disable_raw_mode, ClearType}, ExecutableCommand, }; use std::io::{stdout, Write}; use std::fs::File; fn main() -> std::io::Result<()> { let mut stdout = stdout(); let mut buffer = String::new(); enable_raw_mode()?; stdout.execute(crossterm::terminal::Clear(ClearType::All))?; stdout.execute(cursor::MoveTo(0, 0))?; loop { match read()? { Event::Key(event) => match event.code { KeyCode::Char(c) => { buffer.push(c); print!("{}", c); stdout.flush()?; } KeyCode::Enter => { buffer.push('\n'); print!("\r\n"); stdout.flush()?; } KeyCode::Backspace => { buffer.pop(); stdout.execute(cursor::MoveLeft(1))?; print!(" "); stdout.execute(cursor::MoveLeft(1))?; stdout.flush()?; } KeyCode::Esc => { break; } _ => {} }, _ => {} } } disable_raw_mode()?; let mut file = File::create("output.txt")?; write!(file, "{}", buffer)?; Ok(()) }
inputファイルを読み込んで、出力
use crossterm::{ cursor, event::{read, Event, KeyCode}, terminal::{enable_raw_mode, disable_raw_mode, ClearType}, ExecutableCommand, }; use std::io::{stdout, Write}; use std::fs::{File, read_to_string}; fn main() -> std::io::Result<()> { let mut stdout = stdout(); let mut buffer = String::new(); let initial_text = match read_to_string("input.txt") { Ok(content) => content, Err(_) => String::new(), }; buffer.push_str(&initial_text); enable_raw_mode().expect("Failed to enable raw mode"); stdout.execute(crossterm::terminal::Clear(ClearType::All))?; stdout.execute(cursor::MoveTo(0, 0))?; let mut row: u16 = 0; let mut col: u16 = 0; for ch in buffer.chars() { match ch { '\n' => { print!("\r\n"); row += 1; col = 0; } _ => { print!("{}", ch); col += 1; } } } stdout.flush()?; stdout.execute(cursor::MoveTo(col, row))?; loop { match read()? { Event::Key(event) => match event.code { KeyCode::Char(c) => { buffer.push(c); print!("{}", c); stdout.flush()?; } KeyCode::Enter => { buffer.push('\n'); row += 1; print!("\r\n"); stdout.flush()?; } KeyCode::Backspace => { buffer.pop(); stdout.execute(cursor::MoveLeft(1))?; print!(" "); stdout.execute(cursor::MoveLeft(1))?; stdout.flush()?; } KeyCode::Esc => { break; } _ => {} }, _ => {} } } disable_raw_mode()?; let mut file = File::create("output.txt")?; write!(file, "{}", buffer)?; Ok(()) }
input.txtを行単位で読み込んで出力するなどの工夫が必要