Home > front end >  How to correctly support arrow keys(↑↓←→) in C language stdin?
How to correctly support arrow keys(↑↓←→) in C language stdin?

Time:11-01

I intend to develop a command line tool by C in the CentOS, with the following code:

// client.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <unistd.h>
#include <termios.h>

int main(int argc, char *argv[])
{
    char command[128];

    while (1)
    {
        memset(command, 0, 128);
        printf("cli > ");
        if (fgets(command, 128, stdin) != NULL)
        {
            if (strcmp(command, "exit\n") == 0)
                break;
            if (strcmp(command, "\n") == 0)
                continue;
            printf("do something ... %s", command);
        }
    }

    return 0;
}

The program can works, but it doesn't execute the way I expect it to when I press the arrow keys.

I have finished typing a simple SQL and now the cursor stays after the semicolon.

[root@olap tests]# gcc client.c 
[root@olap tests]# ./a.out 
cli > selectt * from table_001;

But I misspelled the first keyword, it should be select, not selectt. I am now pressing the left arrow key(←) to try to fix this mistake. But the cursor didn't move properly as I expected, and it turned into the following.

[root@olap tests]# gcc client.c 
[root@olap tests]# ./a.out 
cli > selectt * from table_001;^[[D^[[D^[[D^[[D^[[D^[[D^[[D

How should I modify the program to solve this problem?

I hope get help from people who are good at C development.

Thank you all

CodePudding user response:

You might want to try the ncurses library with getch

This sample code demonstrates how you can detect arrow keys and have a CLI prompt:

#include <string.h>
#include <ncurses.h>

int main(int argc, char *argv[])
{
  int ch,i;
  char command[128];

  initscr();
  clear();
  noecho();
  cbreak();
  keypad(stdscr, true);

  while (1) {
      printw("cli> ");
      for (i=0;;i  ) {
          ch=getch();
            
          if (ch==KEY_UP||ch==KEY_LEFT||ch==KEY_RIGHT||ch==KEY_DOWN) {
              /* printw("arrow keys pressed!");
              command[i]='\0';
              break; */
              i--;
          }
          else if (ch=='\n') {
              if (i>0)
                  printw("\n");
              command[i]='\0';
              break;
          }
          else {
              command[i]=ch;
              printw("%c",ch);
          }
      }
      if (strcmp(command, "exit") == 0)
          break;
      else
          printw("%s\n", command);
        
    }
    endwin();

    return 0;
}

CodePudding user response:

Consider using the readline library, you can find it here. It supports arrow keys, a input history and input of any length (if configured).

char *input = readline("cli >");
if (input)
{
    if (strcmp(command, "exit\n") == 0)
    ...
    free(input);
}
  • Related