JLine3のLineReaderのメモ。
LineReaderは、JLine3でユーザーからの入力を扱うクラス。
import java.io.IOException; import org.jline.reader.LineReader; import org.jline.reader.LineReaderBuilder; import org.jline.terminal.Terminal; import org.jline.terminal.TerminalBuilder;
public class JLineExample { public static void main(String[] args) throws IOException { try (Terminal terminal = TerminalBuilder.terminal()) { LineReader lineReader = LineReaderBuilder.builder() // .terminal(terminal) // .build(); for (;;) { String line = lineReader.readLine("jline> "); // 文字列引数はプロンプト terminal.writer().println(line); } } } }
readLine()を呼ぶと、プロンプトが表示されて、ユーザーからの入力待ちになる。
ユーザーのキー操作に伴う特殊な処理(カーソルの上下やCtrl+Rを押したときの履歴の表示等)はLineReader(具象クラスはLineReaderImpl)が行う。
ユーザーが入力した文字列の解析はParserが行う。(→DefaultParser)
Parser.parse()がEOFErrorを返すと、LineReaderは次の行の入力を待ち、元の文字列と結合して再びParser.parse()を呼び出す。(→複数行の入力)
エスケープ文字が設定されている場合、エスケープ処理された文字列がreadLine()から返ってくる。(デフォルトでは「\
」がエスケープ文字として設定されている)
また、その文字列を履歴に登録するのもLineReaderが行っている。
デフォルトでは、ユーザーがエスケープ文字を入力すると、エスケープ処理された文字列がreadLine()から返される。[2022-09-05]
(例えば「\exit
」という文字列を入力すると「exit
」が返される)
「\
」から始まる文字列をコマンドとして扱いたいような場合は、エスケープ処理を抑止するのが良いだろう。
エスケープ処理の実施の有無はDISABLE_EVENT_EXPANSIONオプションで制御できる。
LineReader lineReader = LineReaderBuilder.builder() // .terminal(terminal) // .option(Option.DISABLE_EVENT_EXPANSION, true) // エスケープ処理を無効にする .build();
lineReader.setOpt(Option.DISABLE_EVENT_EXPANSION); // エスケープ処理を無効にする lineReader.unsetOpt(Option.DISABLE_EVENT_EXPANSION); // エスケープ処理を有効にする(デフォルト) lineReader.option(Option.DISABLE_EVENT_EXPANSION, true); // エスケープ処理を無効にする
※エスケープ処理を無効にすると、行継続も出来なくなる
デフォルトでは、閉じ括弧「)]}
」を入力すると、対応する開き括弧の位置にカーソルが一時的に移動する(blinkする)。
LineReaderのBLINK_MATCHING_PARENでblinkの時間を指定できる。(デフォルト値は500[ミリ秒])
0以下を指定するとblinkしなくなる。
LineReader lineReader = LineReaderBuilder.builder() // .terminal(terminal) // .variable(LineReader.BLINK_MATCHING_PAREN, 0) // blinkを抑止 .build();
LineReader lineReader = LineReaderBuilder.builder() // .terminal(terminal) // .build(); if (terminal.getType().equals(Terminal.TYPE_DUMB)) { // DumbTerminalだけblinkを抑止 lineReader.setVariable(LineReader.BLINK_MATCHING_PAREN, 0); }
参考: JLine3のdemoのRepl.java
ただし、DumbTerminalではblinkがきちんと動作しない。 (jline 3.21.0)
閉じ括弧を含む入力データ自体が画面上にそのまま表示される。
そのため、自分でも入力データを表示していると、二重に表示されているように見えてしまう。
DumbTerminalでの使用時に、二重に表示されてしまう例 jline> (a) (a)(a) jline> } }}
BLINK_MATCHING_PARENに0以下を指定するとblinkしなくなるので、DumbTerminalで余計な表示がされなくなる。