如何在不按 Enter 的情况下捕获单个按键

问题描述 投票:0回答:1

如何使用 Zig 在不按 Enter 的情况下捕获终端中的单个击键?

这是我正在尝试的:

const std = @import("std");

const c = @cImport({
    @cInclude("termios.h");
    @cInclude("unistd.h");
    @cInclude("stdlib.h");
});

var orig_termios: c.termios = undefined;

pub fn enableRawMode() void {
    _ = c.tcgetattr(c.STDIN_FILENO, &orig_termios);
    _ = c.atexit(disableRawMode);

    var raw: c.termios = undefined;
    const flags = c.ICANON;
    raw.c_lflag &= ~flags;

    _ = c.tcsetattr(c.STDIN_FILENO, c.TCSANOW, &orig_termios);
}

pub fn disableRawMode() callconv(.C) void {
    _ = c.tcsetattr(c.STDIN_FILENO, c.TCSANOW, &orig_termios);
}

pub fn main() !void {
    enableRawMode();

    var char: u8 = undefined;
    const stdin = std.io.getStdIn().reader();

    char = try stdin.readByte();
    std.debug.print("char: {c}\n", .{char});
}

这无法编译,因为我无法分配我的标志。 我收到错误:

main.zig:16:20: error: type 'c_ulong' cannot represent integer value '-257'
    raw.c_lflag &= ~flags;
                   ^~~~~~

我已经在 C 语言中运行了类似的代码,所以我试图将其适应 Zig:

#include <termios.h>

void buffer_off(struct termios *term) {
  tcgetattr(STDIN_FILENO, term);
  term->c_lflag &= ~ICANON;
  tcsetattr(STDIN_FILENO, TCSANOW, term);
}
terminal stdio zig
1个回答
0
投票

我学习了 Zig 方式来禁用/启用终端缓冲:

const stdin = std.io.getStdIn();

pub fn buffer_on(stdin: *const std.fs.File) !void {
    const term = try std.posix.tcgetattr(stdin.handle);
    try std.posix.tcsetattr(stdin.handle, .NOW, term);
}

pub fn buffer_off(stdin: *const std.fs.File) !void {
    var term = try std.posix.tcgetattr(stdin.handle);
    term.lflag.ICANON = false;
    try std.posix.tcsetattr(stdin.handle, .NOW, term);
}

调用

buffer_off()
使得
stdin.reader().readByte()
不再需要按 Enter 键。 然后在
main()
结束时,我致电
buffer_on()
将我的终端恢复正常。

© www.soinside.com 2019 - 2024. All rights reserved.