繁体   English   中英

使用Swift中的命令行工具更新当前行

[英]Update current line with command line tool in Swift

我在Swift中构建了一个OS X命令行工具(Objective-C中的同样问题),用于下载某些文件。 我正在尝试使用下载进度更新命令行。 不幸的是,我无法阻止print语句跳转到下一行。

根据我的研究,回车\\r应该跳到同一行的开头(而\\n会插入一个新行)。

所有测试都在OS X终端应用程序中执行,而不是在Xcode控制台上执行。

let logString = String(format: "%2i%% %.2fM \r", percentage, megaBytes)
print(logString)

仍然,显示器插入一个新行。 怎么预防这个?

注意:这在Xcode的调试器窗口中不起作用,因为它不是真正的终端仿真器,并且不完全支持转义序列。 因此,要进行测试,您必须编译它,然后在终端窗口中手动运行它。

\\r应该可以在大多数终端中移动到当前行的开头,但是你还应该看看VT100终端控制转义序列 他们通过在Swift中发送转义字符\\u{1B} ,然后发送命令来工作。 (警告:他们制作一些非常难看的字符串定义)

你可能需要的是\\u{1B}[K ,它清除从当前光标位置到结尾的行。 如果你不这样做,你的进度输出长度不一样,你会得到以前的print语句留下的文物。

其他一些有用的是:

  • 移动到任何(x,y)位置: \\u{1B}[\\(y);\\(x)H 注意: xy是用字符串插值插入的Int
  • 保存光标状态和位置: \\u{1B}7
  • 恢复光标状态和位置: \\u{1B}8
  • 清除屏幕: \\u{1B}[2J

您还可以执行有趣的操作,例如设置文本前景色和背景色。

如果由于某种原因你无法使\\r工作,你可以通过在打印logString之前保存光标状态/位置然后在以下情况之后恢复它来解决它:

let logString = String(format: "\u{1B}7%2i%% %.2fM \u{1B}8", percentage, megaBytes)
print(logString)

或者在打印之前移动到预定义的(x,y)位置:

let x = 0
let y = 1 // Rows typically start at 1 not 0, but it depends on the terminal and shell
let logString = String(format: "\u{1B}[\(y);\(x)H%2i%% %.2fM ", percentage, megaBytes)
print(logString)

您的示例仅适用于实际命令行,而不适用于调试器控制台。 而且你还需要为每次迭代刷新stdout,如下所示:

var logString = String(format: "%2i%% %.2fM \r", 10, 5)
print(logString)
fflush(__stdoutp)

下面是一个示例,假设某些异步任务正在进行,并且回调会传递Progress类型。

// Print an empty string first otherwise whichever line is above the printed out progress will be removed
print("")

let someProgressCallback: ExampleAsyncCallbackType = { progress in
  let percentage = Int(progress.fractionCompleted * 100)

  print("\u{1B}[1A\u{1B}[KDownloaded: \(percentage)%")
}

关键部分是\\u{1B}[1A\\u{1B}[K然后你要打印到屏幕后面的任何内容。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM