【Python】editor

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を行単位で読み込んで出力するなどの工夫が必要