Go言語(golang)でTUIアプリを作ろう ( その10 TextAreaの追加 )
tviewのfork版を発見する。
[1] tviewの複数行編集サポートについて
tviewにおける複数行編集サポート(TextArea)については、すでに課題として上がっていました。
これを見ますと、かなり積極的なやり取りがあったようですが、結局、tviewに組み込まれることなく放置されてしまったようです。
このような状況ですから、誰かが「これを引き継いで対応しているのではないか」と調べてみると、tviewからのfork版があることが判明。
Forked from Konstantin8105/tviewとありますから、さらなるForkなのでしょう。ドキュメントを見ると、確かにTextAreaが含まれています
TextArea: A minimal text multiline editor.
という表示が目を引きます。
[2] TextAreaの利用について
このtviewをそのまま使うことも考えたのですが、本家のほうが進んでしまっている部分(例えばFlexのメソッド)などもあって、全面的に置き換えることは出来ないと判断しました。しかたがないので、このFork版のソースを切り出して、別メソッドとして使用することとします。
ソースを見ると、TextAreaはTextViewと連動しており、またutil.goの関数の一部を使用しているようなので、この3ファイルを切り出して、mytviewパッケージ内にマージすることで対応しました。ファイル名は下記のとおり。
mytview/
mytextarea.go
mytextview.go
myutil.go
下記を修正しました。
(1) バグ対応
- TextArea設定行数以上のテクストがある場合、上カーソルキーで上部にスクロールした時、Textが崩れてしまう。
- TextAreaにFocusがない状態でも、カーソルが表示されてしまう。
(2) メソッドの追加
カーソルキーによるFocus移動サポートのため、下記のメソッドを追加。
func (f *MyTextArea) FirstLine() bool
func (f *MyTextArea) LastLine() bool
その他、別パッケージするための辻褄合わせなど。
[3] プログラムでの利用
今回は、その8で作成したDetail画面の最下部に複数行を表示、編集するTextAreaフィールドを追加します。
プログラムへの組み込みは、下記のようなコードとなります。
// -------------------------------------------------
// detail body
// -------------------------------------------------
func (self *Detail) detailBody(pages *tview.Pages, header *tview.Flex, footer *tview.Flex, common *Common) *tview.Flex {
var focusPrimitives []tview.Primitive
body := tview.NewFlex().SetDirection(tview.FlexRow)
btnCategory := myButton("Category")
editField01 := myEdit("フィールド01", common.cols)
editField02 := myEdit("フィールド02", common.cols)
// --> TextArea
editNote := mytview.NewMyTextArea().SetText("FirstLine\nNextLine")
:
:
Focus移動については、TextArea内の現在行位置によって判断を行います。あまりスマートではないですけどね。
case tcell.KeyDown:
if !editNote.HasFocus() {
mySetFocus(self.app, focusPrimitives, false)
return nil
} else if editNote.LastLine() {
mySetFocus(self.app, focusPrimitives, false)
return nil
}
case tcell.KeyUp:
if btnCategory.HasFocus() {
myFlexFocus(self.app, header, false)
return nil
} else if !editNote.HasFocus() {
mySetFocus(self.app, focusPrimitives, true)
return nil
} else if editNote.FirstLine() {
mySetFocus(self.app, focusPrimitives, true)
return nil
}
以上で、TextAreaによる複数行編集がサポートされました。
[4] プログラムの構造と実行
プログラムのディレクトリ構造は下記のようになります。
cmd/
main.go
tui/
application.go
common.go
list.go
mywidget.go
mytview
mydialog.go
mytextarea.go
mytextview.go
myutil.go
go.mod
go.sum
実行は前回までと同様です。
go run cmd/main.go
以上で、懸案だった複数行入力を実装することが出来ました。
ここまで数回に渡って、tviewの概要と主なPrimitiveを説明してきました。紹介した部品を活用することで、golangによるTUIアプリケーション開発は可能になると思います。
ソースコードについて
GitHubに登録しました。今回のコードは、Section10となります。
https://github.com/kubemq-hub/tviewのコードを改変して使用しています。