Acorn.jl/src/terminal.jl

138 lines
4.0 KiB
Julia

import Base.==
@enum(Key,
BACKSPACE = (@static is_windows() ? 8 : 127),
ARROW_LEFT = 1000,
ARROW_RIGHT,
ARROW_UP,
ARROW_DOWN,
DEL_KEY,
HOME_KEY,
END_KEY,
PAGE_UP,
PAGE_DOWN,
S_ARROW_UP,
S_ARROW_DOWN,
S_ARROW_LEFT,
S_ARROW_RIGHT,
C_ARROW_UP,
C_ARROW_DOWN,
C_ARROW_LEFT,
C_ARROW_RIGHT)
==(c::UInt32, k::Key) = c == UInt32(k)
==(k::Key, c::UInt32) = c == UInt32(k)
==(c::Char, k::Key) = UInt32(c) == UInt32(k)
==(k::Key, c::Char) = UInt32(c) == UInt32(k)
ctrl_key(c::Char)::UInt32 = UInt32(c) & 0x1f
# For debugging
function printNextKey()
term = Base.Terminals.TTYTerminal(get(ENV, "TERM", @static is_windows() ? "" : "dumb"), STDIN, STDOUT, STDERR)
Base.Terminals.raw!(term, true)
c = readNextChar()
print("Code: $(UInt32(c)), Char: $(Char(c))")
Base.Terminals.raw!(term, true)
return nothing
end
readNextChar() = Char(read(STDIN,1)[1])
function readKey() ::UInt32
c = readNextChar()
# Escape characters
if c == '\x1b'
STDIN.buffer.size < 3 && return '\x1b'
esc_a = readNextChar()
esc_b = readNextChar()
if esc_a == '['
if esc_b >= '0' && esc_b <= '9'
STDIN.buffer.size < 4 && return '\x1b'
esc_c = readNextChar()
if esc_c == '~'
if esc_b == '1'
return HOME_KEY
elseif esc_b == '4'
return END_KEY
elseif esc_b == '3'
return DEL_KEY
elseif esc_b == '5'
return PAGE_UP
elseif esc_b == '6'
return PAGE_DOWN
elseif esc_b == '7'
return HOME_KEY
elseif esc_b == '8'
return END_KEY
else
return '\x1b'
end
elseif esc_c == ';'
STDIN.buffer.size < 6 && return '\x1b'
esc_d = readNextChar()
esc_e = readNextChar()
if esc_d == '2'
# shift + arrorw
if esc_e == 'A'
return S_ARROW_UP
elseif esc_e == 'B'
return S_ARROW_DOWN
elseif esc_e == 'C'
return S_ARROW_RIGHT
elseif esc_e == 'D'
return S_ARROW_LEFT
else
return '\x1b'
end
elseif esc_d == '5'
# Ctrl + arrow
if esc_e == 'A'
return C_ARROW_UP
elseif esc_e == 'B'
return C_ARROW_DOWN
elseif esc_e == 'C'
return C_ARROW_RIGHT
elseif esc_e == 'D'
return C_ARROW_LEFT
else
return '\x1b'
end
end
end
else
# Arrow keys
if esc_b == 'A'
return ARROW_UP
elseif esc_b == 'B'
return ARROW_DOWN
elseif esc_b == 'C'
return ARROW_RIGHT
elseif esc_b == 'D'
return ARROW_LEFT
elseif esc_b == 'H'
return HOME_KEY
elseif esc_b == 'F'
return END_KEY
else
return '\x1b'
end
end
elseif esc_a == 'O'
if esc_a == 'H'
return HOME_KEY
elseif esc_a == 'F'
return END_KEY
end
end
return '\x1b'
else
return c;
end
end