在原始模式下使用termion时如何创建新行?

Eri*_*mpo 1 console stdout rust

我正在使用termion crate来捕获用户输入键,termion::raw::IntoRawMode就像事件监听器一样.我无法在控制台中打印新行,因为stdout处于"原始模式"并且\n无法识别为新行.我不知道如何在draw_user调用方法时禁用原始模式,然后返回原始模式以便再次侦听键事件.

第二行以白色空格开头,但我不知道为什么:

在此输入图像描述

这是我的代码:

extern crate termion;

use termion::event::Key;
use termion::input::TermRead;
use termion::raw::IntoRawMode;
use std::io::{stdin, stdout, Write};

fn main() {
    let mut x: u16 = 1;
    let mut y: u16 = 1;
    // Get the standard input stream.
    let stdin = stdin();
    // Get the standard output stream and go to raw mode.
    let mut stdout = stdout().into_raw_mode().unwrap();
    write!(
        stdout,
        "{}{}{}",
        // Clear the screen.
        termion::clear::All,
        // Goto (1,1).
        termion::cursor::Goto(1, 1),
        // Hide the cursor.
        termion::cursor::Hide
    ).unwrap();
    // Flush stdout (i.e. make the output appear).
    stdout.flush().unwrap();

    for c in stdin.keys() {
        // Clear the current line.
        write!(
            stdout,
            "{}{}{}",
            termion::cursor::Goto(1, 1),
            termion::clear::CurrentLine,
            termion::clear::BeforeCursor
        ).unwrap();

        // Print the key we type...
        match c.unwrap() {
            // Exit.
            Key::Char('q') => break,
            Key::Ctrl('c') => break,
            Key::Left => {
                x -= 1;
                draw_user(&mut x, &mut y);
            }
            Key::Right => {
                x += 1;
                draw_user(&mut x, &mut y);
            }
            Key::Up => {
                y -= 1;
                draw_user(&mut x, &mut y);
            }
            Key::Down => {
                y += 1;
                draw_user(&mut x, &mut y);
            }
            _ => println!(""),
        }
        stdout.flush().unwrap();
    }
    // Show the cursor again before we exit.
    write!(
        stdout,
        "{}{}",
        termion::cursor::Show,
        termion::clear::AfterCursor
    ).unwrap();
    // Flush again.
}

fn draw_user(x: &mut u16, y: &mut u16) {
    let termsize = termion::terminal_size().ok();
    let termwidth = termsize.map(|(w, _)| w - 10).unwrap();
    let termheight = termsize.map(|(_, h)| h).unwrap();
    if *x < 1 {
        *x = 1;
    }
    if *x > termwidth {
        *x = termwidth;
    }
    if *y < 1 {
        *y = 1;
    }
    if *y > termheight {
        *y = termheight;
    }
    //println!("x:{}, y:{}", *x, *y);
    for h in 1..termheight + 1 {
        for w in 1..termwidth + 1 {
            //print!("w:{}",w);
            if h == *y && w == *x {
                print!("?");
            } else {
                print!("*");
            }
        }
        println!("");
    }
}
Run Code Online (Sandbox Code Playgroud)

Jmb*_*Jmb 7

严格来说,换行符\n意味着"转到同一位置的下一行".要从行的开头开始,您需要添加回车符\r,这意味着"转到当前行的开头".这就是Windows中的文本文件使用\r\n组合来标记行尾的原因.Unix和MacOS已经确定这种区别对于计算机文件没有意义,并且在空间非常宝贵的情况下一次额外占用一个字节,因此他们决定在文本文件中使用单个字符.出于同样的原因,计算机控制台有两种模式,一种是在收到换行符时自动添加回车符(为了减少通过串行线连接控制台时传输的数据量),另一种模式适用于它们被发送(用于细粒度控制).由于您已调用stdout().into_raw_mode(),因此您处于第二种模式并需要手动输出回车.

这种行为是从旧机械打字机继承而来的,"换行"是将纸张前进一行并且"回车"是允许手动将托架移回起始位置的手柄.

  • 它实际上是`\r\n`,而不是`\n\r`。 (2认同)