When I touch Vim, some action occurs every time I enter a character, so I was technically interested in how it works, so I tried reading the source code.
I know that I can input line by line with getc () and gets (), but I don't know how to process each key input.
I imagined that the simple idea from my own knowledge was to monitor the character input in another thread and notify the main thread when there was a key input.
I remember writing a Ruby console library called wincons.rb a long time ago that it would end after entering a single character, and I was wondering how this was achieved.
You can get the source from the following. http://texcell.co.jp/ruby/Lib/winconsole.html
Looking at it, it seems that it is realized by calling a function called PeekConsoleInputW of win32api.
http://texcell.co.jp/ruby/PLC/rubyc24.html
↑ Looking at the example here, it seems that the key input check is always performed in the loop and it ends when q
comes.
Is the way wincons.rb really correct? I also had a question, so I decided to take a look at the Vim source code as well.
You can get the source code from github. https://github.com/vim/vim
When I searched for the part where PeekConsoleInputW mentioned earlier was used, I found that it was used in the function read_console_input
of src / os_win32.c
.
This read_console_input
seems to be called from quite a few places, and I didn't know which one was directly connected to keyboard input, so I gave up.
mch_inchar
=> tgetch
is suspicious. mch_inchr
is called from ʻui_inchar, and ʻui_inchar
is called in the for loop of the ʻinchar function. Since the for loop keeps rotating until you can get the key input from ui_inchar, I think that this area is the key to the key input, but in this case, it loops in the inchar function and other processing will not work. , I think it's a thread at the parent calling ʻinchar
, but it's speculation.The readline that comes with ruby calls the completion Proc when you press the TAB key. I guess it must have a process such as calling Proc when the TAB key is pressed.
First, code read the readline that comes with ruby
You can see the source of ruby from the following. https://github.com/ruby/ruby
The source for readline is around ʻext / readline`.
After a lot of research, I found that the function that calls Proc looks like readline_attempted_completion_function
. That function is bound to rl_attempted_completion_function
.
The rl_attempted_completion_function
is not in the ruby code, but in the GNU readline code, so read that.
You can see the source of GNU readline from the following. https://github.com/JuliaLang/readline
It's not exactly the real source of GNU readline, but I don't think it's a problem for this understanding.
The rl_attempted_completion_function
is in complete.c
, but I couldn't get to that point by going back in the function.
Looking around here, readline
looks like a root, so I decided to check it step by step from the root.
http://d.hatena.ne.jp/cocoatomo/20071112/1194855728
readline ()
is located in readline.c
. If you follow the function more and more, it seems that kbhit ()
in rl_gather_tyi ()
of ʻinput.c` is the key to key input.
If you look here http://tricky-code.net/mine/c/mc07kbhit.php
The kbhit function returns a non-zero value when any key is pressed, A function that returns 0 if no key is pressed.
It seems that this itself does not determine which key was pressed.
It seems that what is actually taken is to call the read ()
function in rl_getc (stream)
and read one character from the IO passed as an argument.
By turning it around in a loop, it seems that the key input is always checked and checked character by character.
There was no thread.
readline checks for keystrokes in a loop without using threads.
I use kbhit ()
to determine if there was a keystroke
To get the characters, use read ()
to get the characters one by one.
Recommended Posts