環境
- Julia v1.4.2
- OS: ArchLinux
read
や readline
を使うと EOF を入力 (Ctrl-D) したときや Enter を押したときにキーボードから入力したものを取得することができるが、何かしらのキーをタイプする度に入力を取得する方法を紹介する。
# ex.jl using REPL terminal = REPL.Terminals.TTYTerminal(get(ENV, "TERM", Sys.iswindows() ? "" : "dumb"), Base.stdin, Base.stdout, Base.stderr) function readChar(term) c = Char(read(term.in_stream, 1)[1]) println("$(c) $(Int(c))") return c end REPL.Terminals.raw!(terminal, true) while true Char(readChar(terminal)[1]) == 'q' && break end
while loop の print は1文字ずつ入力する毎に出力される。
$ julia ex.jl a 97 b 98 c 99 d 100 e 101 q 113
一方で raw!
を使わない場合だと、Enter
が入力されるまで while loop の内容は出力されない。
# ex2.jl using REPL terminal = REPL.Terminals.TTYTerminal(get(ENV, "TERM", Sys.iswindows() ? "" : "dumb"), Base.stdin, Base.stdout, Base.stderr) function readChar(term) c = Char(read(term.in_stream, 1)[1]) println("$(c) $(Int(c))") return c end while true Char(readChar(terminal)[1]) == 'q' && break end
$ julia ex2.jl abcdeq a 97 b 98 c 99 d 100 e 101 q 113
上記の例はスクリプトとして実行したが、これを REPL にコピペしても同じ動きにはならない。raw!
を使っていてもカノニカルモードになってしまう。
julia> using REPL julia> terminal = REPL.Terminals.TTYTerminal(get(ENV, "TERM", Sys.iswindows() ? "" : "dumb"), Base.stdin, Base.stdout, Base.stderr) REPL.Terminals.TTYTerminal("xterm-termite", Base.TTY(RawFD(0x0000000a) paused, 0 bytes waiting), Base.TTY(RawFD(0x0000000d) open, 0 bytes waiting), Base.TTY(RawFD(0x0000000f) open, 0 bytes waiting)) julia> function readChar(term) c = Char(read(term.in_stream, 1)[1]) println("$(c) $(Int(c))") return c end readChar (generic function with 1 method) julia> REPL.Terminals.raw!(terminal, true) true julia> while true Char(readChar(terminal)[1]) == 'q' && break end abced a 97 b 98 c 99 e 101 d 100 10 q q 113
しかし、while loop のなかで raw!
を実行すると raw mode になる。
julia> while true REPL.Terminals.raw!(terminal, true) Char(readChar(terminal)[1]) == 'q' && break end a 97 b 98 c 99 d 100 e 101 q 113
while loop 以外にも function
, begin
, let
など新しくスコープを作るもののなかに raw!
を入れると、そのスコープ内では raw mode になるようである。
参考