實現一個終端文字編輯器來學習golang語言:第二章Raw模式下的輸入輸出

4ma2ingZed發表於2024-08-03

從第二章開始,在每個小節的最後都會有一些程式碼實操作業,你可以選擇自己完成(比較推薦),再對照我的實現方式,當然也可以直接看我的程式碼實現。不過,之後的各個功能實現,我都會基於我先前的程式碼實現版本,在它的基礎上進行擴充套件。

首先,我們先來解決第一章遺留的第一個問題:輸入資料會被stdin快取,直到遇到換行符(也就是按下 Enter 鍵)才被髮送。

進入Raw模式(Raw Mode)

"Raw mode" 是一個終端設定,該設定允許程式直接處理終端的輸入資料。在 "raw mode" 中,輸入的字元不會被終端緩衝,而會立即傳送到程式。這意味著程式可以立即響應使用者的每一個按鍵,而不需要等待使用者按下 Enter 鍵。

此外,在 "raw mode" 中,終端不會處理特殊的控制字元,例如 Ctrl+C(通常用於傳送中斷訊號)或 Ctrl+Z(通常用於掛起程式)。這些字元會直接傳送到程式,程式可以自行決定如何處理它們。

需要注意的是,開啟 "raw mode" 需要對終端和作業系統有深入的理解,並且可能需要特定的平臺相關程式碼支援。在本次專案中我們決定使用 termbox-go 庫來簡化這個過程。以下翻譯自termbox-go庫的介紹:

Termbox是一個庫,它提供了一種簡潔的API,允許程式設計師編寫基於文字的使用者介面。該庫是跨平臺的,既有*nix作業系統上的基於終端的實現,也有Windows作業系統上基於winapi控制檯的實現。基本的想法是以簡潔的方式抽象出所有主要終端和其他類似終端API中可用的最大公共子集的特性。小型API意味著它易於實現,測試,維護和學習,這就是使termbox在其領域中成為一個獨特庫的原因。

透過go get指令引入程式碼庫進入專案

go get -u github.com/nsf/termbox-go

這個庫提供的API介面很多,我們需要了解以下三個函式:

  • termbox.Init()
  • termbox.Size()
  • termbox.PollEvent()
    這裡不在展開,可以看對應庫函式的註釋來了解用途。

作業1 波浪線~

你的第一個任務是在螢幕的最左側繪製一列波浪符(~),就像vim所做的那樣。在我們的文字編輯器中,我們將在編輯的檔案結束後的任何行的開頭繪製一個波浪符,當前你可以使用fmt.Printf來進行繪製。其次當輸入q的時候,結束程式執行。

Code Review 我的實現

  • 首先定義了一個editor結構體代表終端
  • 透過termbox.Size()獲取到終端的寬高,然後不斷列印~,直至到終端底部。
  • 透過termbox.PollEvent()來捕捉終端事件,如果是鍵入q的事件,則標記needQuittrue。這樣每次重新整理終端之前我們就可以根據這個flag決定是繼續重新整理終端還是直接退出。

作業2 波浪線~最佳化

在這個作業中我們對波浪線~的畫法進行最佳化,使用termbox的api進行繪製,同時展示出游標。
需要注意的是當終端正在繪製螢幕時,游標可能會在螢幕中間的某個地方閃現,。為了確保這個閃爍效果不會發生,我們需要在重新整理螢幕之前隱藏游標,並在重新整理完成後立即顯示出來。你需要完成如下功能:

  • 每當termbox.PollEvent捕捉到鍵盤上下左右移動時,同時向對應方向移動終端上的游標
  • 在重新整理螢幕之前將游標隱藏(使用termbox.HideCursor)
  • 重新整理螢幕後,展示游標(使用termbox.SetCursor)
  • 使用termbox.SetCell方法繪製波浪線~
    注意:使用termbox api進行繪製時,繪製行為會被儲存在其內部的buffer中,所以需要在合適的時候呼叫termbox.Flush進行螢幕重新整理

Code Review 我的實現

相關文章