覆盖写入控制台的文本

Overwrite text written to console

本文关键字:文本 控制台 盖写 覆盖      更新时间:2023-10-16

我想实现以下目标:我有一个生成文件的程序,如果给定名称的文件已经存在,它应该打印一个警告,询问用户是否应该覆盖它。它看起来像这样:

Processing file                     test.sdf
Checking SDF file...                [OK]
Parsing SDF...                      [OK]
Generating NDDL model file...       [WARN]
Warning. The file "/home/chris/models/test-model.nddl" already exists. Overwrite? [y/N] 

现在,如果用户决定要做什么,我想将控制台光标倒回到[WARN][字符,并用[OK][FAIL]覆盖它,然后用程序的下一个输出覆盖以下行。

我发现我可以用ANSI控制序列实现这一点。因为我只是在使用Ubuntu,所以我可以接受。

我想到了两个主意:

1)倒回光标,直到我找到字符串[WARN],然后开始再次写入。

2)将光标一行一行向上移动,直到Generating NDDL model file... [WARN]行被删除,并覆盖它,例如Generating NDDL model file... [FAIL]

但是用这两种方法,我都有一个问题,我就是无法解决或找到谷歌的方法…

问题1):我不知道如何读取当前光标位置的字符。但无论如何,我不认为这是个好主意。它似乎不可靠。

问题2):由于输入文件的路径可以是任意的,我无法控制[WARN]出现后打印的行数,所以我只是不知道我应该运行多少std::cout << "33[F" << "33[2K" << std::flush; (move-cursor-one-line-up和clear-all-contents-in-line的ANSI控制序列)。此外,我不知道终端窗口的宽度有多大,所以我也无法计算它(不知道这是否是个好主意,尽管…)

我相信一定有办法做到这一点,但我就是想不出一个好的、可靠的方法来做到这一点。

你们有人知道吗?谢谢你的帮助

X/Y问题

如果你坚持要直接操作控制台,那么为什么不完全返回最后两行呢?当你可以重印整篇文章的时候,为什么还要编辑一行呢?此外,你不能保证能够以相同的方式在平台和shell之间操作每个控制台。

当你打印出来的行,你应该很容易知道有多少备份和覆盖。如果你做不到,那就清空屏幕,然后再把所有的东西写回来。

解决方案

呈现这样一个接口的正确方法是使用curses库(或等效库)并完全控制控制台的输出。这给了你完全的控制。

如果你认为这是过度使用,那么你注定要重新创建curses的功能,最后以混乱告终。

嗯,有一些可能性使用回车符(r),它将带您到当前行的开头,或者使用退格符(b),它将倒回一个字符位置,然后您只需重新写一遍。没有诅咒。没有ANSI的疯狂