LINUX.ORG.RU

[C] перехват курсорных клавиш

 


0

0

Можно ли сделать перехват курсорных клавиш средствами стандартных библиотек С? Если конкретно, то нужно чтобы консольная прога запоминала команды и при нажатии клавиши "вверх" выдавала последнюю введенную команду. Так сделано в bash, но просматривая его исходники что-то пока не удается выловить идею.

Если нельзя с помощью голого С, то как сделать это по-другому?

Ответ на: комментарий от alex_custov

> libreadline

Да, спасибо, похоже оно используется в bash.

Еще попробую поискать способы обойтись без сторонних библиотек.

Rarruga
() автор топика
Ответ на: комментарий от Rarruga

Расследование показывает, что bash использует libreadline, которая, в свою очередь, использует ncurses.

Будем копать дальше..

Rarruga
() автор топика

ncurses нужна, потому что все терминалы работают по-разному, это слой переносимости, который никто в здравом уме не захочет переделывать (linux-консоль по alt+f1, xterm и gnome-terminal - это всё "разные терминалы"). libreadline - это реализация непосредственно того, что нужно ("как в bash"). Естественно, она использует ncurses.

Кроме того, ncurses нужна не просто для того, чтобы перехватывать нажатия на курсор. Для того, чтобы удержать курсор ввода на строке и надёжно затереть уже введенный текст, тоже нужна ncurses. Think about it.

anonymous
()
Ответ на: комментарий от Rarruga

Можно вручную обрабатывать нажатые клавиши например так:

#include <termios.h> 
#include <assert.h> 

int getch(void) {
      int c = 0;

      struct termios org_opts, new_opts;
      int res = 0;
          //-----  store old settings -----------
      res = tcgetattr(STDIN_FILENO, &org_opts);
      assert(res==0);
          //---- set new terminal parms --------
      memcpy(&new_opts, &org_opts, sizeof(new_opts));

      new_opts.c_lflag &= ~(ICANON | ECHO);
      new_opts.c_cc[VTIME] = 0;
      new_opts.c_cc[VMIN] = 1;

      tcsetattr(STDIN_FILENO, TCSANOW, &new_opts);
      c = getchar();
          //------  restore old settings ---------
      res = tcsetattr(STDIN_FILENO, TCSANOW, &org_opts);
      assert(res==0);
      return(c);
}

    int ch = 0;
    while(1)
        {
            ch = getch();
            if(ch != 27) putchar(ch);
            else
                {
                 // обработка функциональных клавиш
                }
         } 

Кривовато, но работать должно :)

koTuk
()
Ответ на: комментарий от Valeriy_Onuchin

> тоже нужна ncurses. Think about it.

возможно, говорим о разных readline
То, что я юзаю обрабатывает ограниченное число клавиш,
которые есть во всех клавах. Вот коммент из сорца:


************************** End-User Interface ***************************

Entering printable keys generally inserts new text into the buffer (unless
in overwrite mode, see below). Other special keys can be used to modify
the text in the buffer. In the description of the keys below, ^n means
Control-n, or holding the CONTROL key down while pressing "n". M-B means
Meta-B (or Alt-B). Errors will ring the terminal bell.

^A/^E : Move cursor to beginning/end of the line.
^F/^B : Move cursor forward/backward one character.
^D : Delete the character under the cursor.
^H, DEL : Delete the character to the left of the cursor.
^K : Kill from the cursor to the end of line.
^L : Redraw current line.
^O : Toggle overwrite/insert mode. Initially in insert mode. Text
added in overwrite mode (including yanks) overwrite
existing text, while insert mode does not overwrite.
^P/^N : Move to previous/next item on history list.
^R/^S : Perform incremental reverse/forward search for string on
the history list. Typing normal characters adds to the current
search string and searches for a match. Typing ^R/^S marks
the start of a new search, and moves on to the next match.
Typing ^H or DEL deletes the last character from the search
string, and searches from the starting location of the last search.
Therefore, repeated DEL's appear to unwind to the match nearest
the point at which the last ^R or ^S was typed. If DEL is
repeated until the search string is empty the search location
begins from the start of the history list. Typing ESC or
any other editing character accepts the current match and
loads it into the buffer, terminating the search.
^T : Toggle the characters under and to the left of the cursor.
^U : Kill from beginning to the end of the line.
^Y : Yank previously killed text back at current location. Note that
this will overwrite or insert, depending on the current mode.
M-F/M-B : Move cursor forward/backward one word.
M-D : Delete the word under the cursor.
^SPC : Set mark.
^W : Kill from mark to point.
^X : Exchange mark and point.
TAB : By default adds spaces to buffer to get to next TAB stop
(just after every 8th column), although this may be rebound by the
programmer, as described below.
NL, CR : returns current buffer to the program.

DOS and ANSI terminal arrow key sequences are recognized, and act like:

up : same as ^P
down : same as ^N
left : same as ^B
right : same as ^F

Valeriy_Onuchin ★★
()
Ответ на: комментарий от koTuk

> Можно вручную обрабатывать нажатые клавиши например так:

Попытался использовать этот вариант. Пока не получается сделать так, как мне нужно. Судя по манам на этот termios у меня ничего и не получится.

Rarruga
() автор топика
Ответ на: комментарий от Rarruga

>Расследование показывает, что bash использует libreadline, которая, в свою очередь, использует ncurses.

>Будем копать дальше..

А у кого-то на линуксе нету ncurses?

Absurd ★★★
()

Посмотри termcap.
Я как-то давно юзал, по-моему это то, что тебе нужно...

borodun
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.