【问题标题】:How to clear the command line?如何清除命令行?
【发布时间】:2015-10-13 09:14:54
【问题描述】:

在 C/C++ 标准库中是否有与 system 函数等效的 Rust?具体来说,我正在尝试使用cls 来清除命令行。

【问题讨论】:

    标签: rust


    【解决方案1】:

    上述方法对我不起作用

    以下方法在windows cmd中有效

    Cargo.toml

    [dependencies]
    winapi = "0.2.8"
    kernel32-sys = "0.2.1"
    

    代码

    extern crate kernel32;
    extern crate winapi;
    
    use winapi::HANDLE;
    use winapi::wincon::CONSOLE_SCREEN_BUFFER_INFO;
    use winapi::wincon::COORD;
    use winapi::wincon::SMALL_RECT;
    use winapi::WORD;
    use winapi::DWORD;
    
    static mut CONSOLE_HANDLE: Option<HANDLE> = None;
    
    
    fn get_output_handle() -> HANDLE {
        unsafe {
            if let Some(handle) = CONSOLE_HANDLE {
                return handle;
            } else {
                let handle = kernel32::GetStdHandle(winapi::STD_OUTPUT_HANDLE);
                CONSOLE_HANDLE = Some(handle);
                return handle;
            }
        }
    }
    
    fn get_buffer_info() -> winapi::CONSOLE_SCREEN_BUFFER_INFO {
        let handle = get_output_handle();
        if handle == winapi::INVALID_HANDLE_VALUE {
            panic!("NoConsole")
        }
        let mut buffer = CONSOLE_SCREEN_BUFFER_INFO {
            dwSize: COORD { X: 0, Y: 0 },
            dwCursorPosition: COORD { X: 0, Y: 0 },
            wAttributes: 0 as WORD,
            srWindow: SMALL_RECT {
                Left: 0,
                Top: 0,
                Right: 0,
                Bottom: 0,
            },
            dwMaximumWindowSize: COORD { X: 0, Y: 0 },
        };
        unsafe {
            kernel32::GetConsoleScreenBufferInfo(handle, &mut buffer);
        }
        buffer
    }
    
    fn clear() {
        let handle = get_output_handle();
        if handle == winapi::INVALID_HANDLE_VALUE {
            panic!("NoConsole")
        }
    
        let screen_buffer = get_buffer_info();
        let console_size: DWORD = screen_buffer.dwSize.X as u32 * screen_buffer.dwSize.Y as u32;
        let coord_screen = COORD { X: 0, Y: 0 };
    
        let mut amount_chart_written: DWORD = 0;
        unsafe {
            kernel32::FillConsoleOutputCharacterW(
                handle,
                32 as winapi::WCHAR,
                console_size,
                coord_screen,
                &mut amount_chart_written,
            );
        }
        set_cursor_possition(0, 0);
    }
    
    fn set_cursor_possition(y: i16, x: i16) {
        let handle = get_output_handle();
        if handle == winapi::INVALID_HANDLE_VALUE {
            panic!("NoConsole")
        }
        unsafe {
            kernel32::SetConsoleCursorPosition(handle, COORD { X: x, Y: y });
        }
    }
    

    示例

    fn main() {
        loop {
            let mut input = String::new();
            std::io::stdin()
                .read_line(&mut input)
                .expect("Failed to read line");
    
            println!("You typed: {}", input);
    
            if input.trim() == "clear" {
                clear();
            }
        }
    }
    

    【讨论】:

    • 其他 cmets 也没有为我工作。这行得通。但对于其他人来说,值得注意的是,您可能需要在let coord_screen = COORD { X: 0, Y: 0 }; 之后执行类似for _ in 0..screen_buffer.dwSize.Y { println!(""); } 的操作。为什么?因为这个发布的方法并不总是清除所有内容,但如果你输出换行符,它肯定会清除所有内容。我有特殊的颜色块没有被这种方法清除,虽然 ascii 文本是
    【解决方案2】:

    您可以通过libc crate 使用C's system function。但幸运的是有一个更好的方法:std::process::Command

    调用cls 的一种快速而肮脏的方式是

    if std::process::Command::new("cls").status().unwrap().success() {
        println!("screen successfully cleared");
    }
    

    【讨论】:

    • 小心! cls 仅存在于 Windows 上。在 *nix 中,命令是 clear。通常,不建议为此使用系统命令。这需要做很多工作:查找命令、启动进程、绑定标准输出等。在这种情况下,我会尽量坚持使用 libc。
    • 我也想知道为什么这被视为“更好”。它既不便携又拗口,有什么更好的呢?
    • 它不是不安全的,它使用 Rust 的 Result 类型来保证你检查它是否有效。即使你只是简单地将程序带到 linux 上,至少你会得到一个很好的失败。如果你想要一个在所有系统上运行的单线,你可以开始链接命令:assert!(Command::new("cls").status().or_else(|_| Command::new("clear")).unwrap().success())
    • 我想知道是否有一个与终端相关的板条箱有明确的命令……但什么都找不到。
    【解决方案3】:

    oli_obk,实际上我认为这是正确的 - 它适用于我在 Linux 上的 Rust:

    assert!( std::process::Command::new("cls").status().or_else(|_| std::process::Command::new("clear").status()).unwrap().success() );
    

    status() 必须使用两次。 (将上面的代码行放在 main 之类的函数中。)

    【讨论】:

      猜你喜欢
      • 2011-04-28
      • 2012-07-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-25
      • 2018-04-22
      • 2012-10-07
      • 2020-04-30
      相关资源
      最近更新 更多