Change input key bindings

151 views
Skip to first unread message

yousef.k...@gmail.com

unread,
May 16, 2016, 5:27:38 PM5/16/16
to julia-users
Hello everyone,

I'm trying to build an application with a command-line interface (CLI).
I want to be able to navigate a command-line menu with arrow keys.

However, I can't figure out how to change the behavior of key strokes, e.g. arrow keys.
I know it's possible to do this by modifying ".juliarc.jl", but I want to be able to achieve my goal from within my application itself.

Anyone know how I may be able to specify behavior for different key strokes?


Thanks,
Yousef

yousef.k...@gmail.com

unread,
May 17, 2016, 10:58:39 AM5/17/16
to julia-users
I've been reading through Julia's initialization and REPL code, but I'm still confused as to how key strokes signal events to happen.

To clear up my intention of this knowledge, I would like to be able navigate command line menus similar to a BIOS for example.
Pressing up would move me to the top button and vice versa down will move me down.
I would capture the events sent from key strokes and afterwards clear the screen then reprint with the correct button highlighted.

I just don't know how to override the default key stroke behaviors or even how to capture them before the REPL does.
Does Julia even allow this kind of control?
Help would be much appreciated.

Thanks,
Yousef


Kevin Squire

unread,
May 17, 2016, 11:10:06 AM5/17/16
to julia...@googlegroups.com
Hi Yousef, 

If you're on Linux or OSX (or somehow run an xterm-compatible terminal on Windows), check out https://github.com/tonyhffong/TermWin.jl.

I haven't used it myself, but it should give you some or most of the terminal navigation that you want.

Cheers,
   Kevin

yousef.k...@gmail.com

unread,
May 17, 2016, 11:40:25 AM5/17/16
to julia-users
Hey Kevin,

Thanks for the reply.
I was looking at the package and saw that it uses an external library that launches a new terminal window.
While that seems to do the job, I would still like to programmatically do keystroke events in native Julia.

Here's a different question: can I somehow hijack the REPL inputs to Julia by writing some kind of C file?
Keep in mind that I've never done any C programming, but I see that ncurses is written in C and it can accept keystrokes in a window other than the REPL window.
Maybe I can do something like that but have my Julia program ccall some function and take control of keystroke events.


Thanks,
Yousef

Yichao Yu

unread,
May 17, 2016, 12:13:40 PM5/17/16
to Julia Users
On Tue, May 17, 2016 at 11:40 AM, <yousef.k...@gmail.com> wrote:
> Hey Kevin,
>
> Thanks for the reply.
> I was looking at the package and saw that it uses an external library that
> launches a new terminal window.
> While that seems to do the job, I would still like to programmatically do
> keystroke events in native Julia.
>
> Here's a different question: can I somehow hijack the REPL inputs to Julia
> by writing some kind of C file?
> Keep in mind that I've never done any C programming, but I see that ncurses
> is written in C and it can accept keystrokes in a window other than the REPL
> window.
> Maybe I can do something like that but have my Julia program ccall some
> function and take control of keystroke events.

I don't think hijacking the REPL is the right way to go since a REPL
is a much higher level abstraction compare to what you want to
implement. You should implement a terminal UI at a level that give you
full control of the terminal screen, not on top of a completely
different terminal UI.

You might want to have a look at https://github.com/Keno/TerminalUI.jl
(0.5 only though). @Keno has much more experience with this and he
might even have some other packages for these.

yousef.k...@gmail.com

unread,
May 17, 2016, 12:46:04 PM5/17/16
to julia-users
The Julia community never ceases to amaze me.
I'll have a look at Keno's package and try to understand how he achieves customized keystroke events.
If I can't, I'll just use the package.


Thank you all for your help,
Yousef

yousef.k...@gmail.com

unread,
May 19, 2016, 6:22:32 AM5/19/16
to julia-users
Greetings all,

So, after much reading through Julia base, I believe I've figured out how to directly read keyboard inputs from the terminal.
First, here is the code:

###
function main()
  raw_mode()
  println("Just type away and see your characters print, line by line.")
  println("Press escape to exit.")
  input = readinput()
  while input != "\e"
    println(input)
    input = readinput()
  end
  println("Goodbye!")
end

raw_mode() = ccall(:jl_tty_set_mode, Int32, (Ptr{Void}, Int32), STDIN.handle, true) == 0 ||
             throw("FATAL: Terminal unable to enter raw mode.")

function readinput()
  input = readavailable(STDIN)
  chars = map(Char, input)
  return join(chars)
end

main()
###

Just paste this code in a .jl file and execute it directly using `julia filename.jl` in your favorite text terminal.
The function "raw_mode" forces the terminal to read from the keyboard directly without having to buffer after an enter key.
The function "readinput" will call "readavailable(STDIN)" to block until a key is pressed.
Once a key is pressed, "readavailable(STDIN)" will return the key pressed in Vector{UInt8}.
The rest of the function just converts that into a String so it is readable, and it's printed afterwards on screen.
This process is looped until the escape key is pressed, indicating that the program must now exit.

NOTE: Some terminals are pseudoterminals, and they are switched to raw mode using a different process. So if you can't get this example up and running, just let me know.

In short, just run the terminal in raw mode and then call on "readavailable(STDIN)" to receive keyboard inputs.
I don't know if this is good practice, but it does the job as expected, at least on Windows 10 x64.
This took me too long to figure out, so I thought I should share it as it may be useful to someone else in the future.


Regards,
Yousef


Reply all
Reply to author
Forward
0 new messages