対象読者
- Rubyの入門書を一読した方
- 練習用にRubyのプログラムを作りたいが良い課題が見つからない方
必要なもの
Ruby本体とお好きなエディタを用意してください。
筆者は以下の環境で執筆しています。
ruby 1.8.6-p111 / SAKURAエディタ / WindowsXPsp2
今回作る物
前回の続きでコンソールベースのテキストエディタを作ります。前回では表示部分を主に作ったので、今回は編集と保存ができるようにしたいと思います。
記事の最後には、下図のようなクラス構成になります。
バグの修正
いきなりですが、前回のソースコードに少しバグがあるので修正してください。
以下、「バグ修正」と書かれた次の行を追記してください。
# カーソルを下へ移動。ウィンドウの下端より下へカーソルが移動 # しようとした場合はスクロール def cursor_down if @cursor_y >= (@window.maxy-1) scroll_down # バグ修正 elsif @cursor_y >= (@data.length-1) # 文章最大行数より下にはカーソルが動かないように else @cursor_y += 1 end ## 中略 ## end
編集モードの追加
前回ではカーソルを動かせるコマンドモード用にHandler
クラスを作りましたが、今回は文字を入力する編集モード用にEditHandler
クラスを追加することにします。編集モードとコマンドモードの切り替えはESCキーで行うようにします。文字の削除は[x]で行うようにします。
require "editwind" class Handler def execute(wind,input_ch) # コマンド入力を処理 case input_ch when 27 # ESC return EditHandler.new when ?x wind.delete ## 中略 ## end end class EditHandler def execute(wind,input_ch) # 文字入力を処理 case input_ch when 27 # ESC return Handler.new else wind.input(input_ch) end return self end end
ここであらかじめ入れておいた「ちいさな仕掛け」を活用します。Handler
クラスを利用しているFe
クラスのメインループではexecute
メソッドの戻り値を、次に使うイベント処理オブジェクトとして受け取っています。(下記参照)
begin while true ch = edit_wind.getch #1文字入力。 # イベント処理クラスで処理分岐を行う handler = handler.execute(edit_wind,ch) end end
Handler
とEditHandler
の両クラスの方では、ESCキーを押されるたびに次に使用するイベント処理オブジェクト(Handler
ではEditHandler
を、EditHandler
ではその逆)をリターンしています。これによりメインループでは現在のモードを意識せずに「押されたキーを受け取りそれをイベント処理オブジェクトに渡す」事に専念できます。
次にEditWind
クラスに、編集モードで文字が入力された場合に呼び出されるメソッドinput
とコマンドモードで[x]を押された時に呼び出されるメソッドdelete
を追加します。下記のようにeditwind.rbに追加してください。
# 1文字(1バイト)入力 def input(input_ch) # ウィンドウ上で一文字挿入 @window.insch(input_ch) # カーソルを微調整 @window.setpos(@cursor_y,@cursor_x+=1) end # 1文字(1バイト)削除 def delete # ウィンドウ上で一文字削除 @window.delch end