使用转义序列刷新前N行并将光标重置到当前行的末尾?

7

这是情况,我想要在终端上进行一些交互,我想启动一个子线程来刷新前N行,并使用主线程处理用户输入。

之后程序将打印可变的字符串,可能是一些日志。

子线程如下:

    let mut count: i32 = 0;
    loop {
        println!("\x1B[2F\x1B[2KHi user1, count:{}\n", count);
        count += 1;
        let ten_millis = time::Duration::from_millis(1000);
        thread::sleep(ten_millis);
    }

e.g.:

----------------
Hi user1, count: 0


Input:  1+1
Output: 2
----------------

刷新代码运行良好,但光标会重置到行首,我想让它始终移动到最后一行的末尾。如何实现这个技巧?非常感谢任何帮助。

2
这是什么编程语言?它不是bash。请删除bash标签并添加适当的标签。这将吸引更多能够更好地回答您问题的人的关注。 - Adam Katz
@AdamKatz 实际上,我认为同样的原则适用于其他语言,我的代码只是一个例子。 - McGrady
3个回答

10

当涉及到移动光标时,您可能会对简单的ANSI转义序列感兴趣:

ANSI转义序列允许您随意在屏幕上移动光标。这对于由shell脚本生成的全屏用户界面更有用,但也可用于提示符中。移动转义序列如下:

Description Sample
将光标置于第L行第C列 \033[<L>;<C>H
将光标置于第L行第C列 \033[<L>;<C>f
向上移动N行 \033[<N>A
向下移动N行 \033[<N>B
向前移动N列 \033[<N>C
向后移动N列 \033[<N>D
清除屏幕,移动到(0,0) \033[2J
删除至行尾 \033[K
保存光标位置 \033[s
恢复光标位置 \033[u

来源: Bash提示符HOWTO: 光标移动

尽管这些ANSI转义序列非常好用,但有时您可能会对tput的使用感兴趣,因为它可以使您的脚本更易读。在此介绍tput可能过于冗长,但上述命令可以这样完成:

描述 示例
将光标放置于第L行,第C列 tput cup <L> <C>
向上移动N行光标 tput cuu <N>
向下移动N行光标 tput cud <N>
向前移动N列光标 tput cuf <N>
向后移动N列光标 tput cub <N>
清除屏幕,移动到(0,0) tput clear
擦除至行尾 tput el
保存光标位置 tput sc
恢复光标位置 tput rc

还有许多其他选项可用。请参见

  • man tput
  • man 5 terminfo
  • 这两个命令都与终端控制有关。`tput` 命令用于在终端上设置和查询属性,比如光标位置和文本颜色。而 `terminfo` 文件则描述了各种类型的终端及其支持的功能和属性。

0

虽然没有完全回答你的问题,但标准的 bash 方法是使用 watch

例如:

watch df -h


0

你可以让子进程“知道”输入正在进行,这种情况下可以使用 println!

  • 附加一个光标下移(即\x1B[B)或者下一行(\x1B[E)的指令,
  • 接着使用提示语长度和当前输入长度总和来在该行中移动,例如光标前进(即\x1B[C),在C之前加上列数作为参数。

类似于:

if (input_length) {
    cursor_down();
    cursor_forward(prompt_length + input_length);
}

让我试一试。 - McGrady
但如果输入字符串是可变的,可能有多行,我能把光标重置到最后一行的末尾吗?\033[s 保存光标位置怎么样? - McGrady
这取决于终端(请参见此处)。 - Thomas Dickey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接