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版のソースを切り出して、別メソッドとして使用することとします。

ソースを見ると、TextAreaTextViewと連動しており、また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のコードを改変して使用しています。