簡體   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