shellCommand.c 18.3 KB
Newer Older
H
hzcheng 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
 *
 * This program is free software: you can use, redistribute, and/or modify
 * it under the terms of the GNU Affero General Public License, version 3
 * or later ("AGPL"), as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#define __USE_XOPEN
S
Shengliang Guan 已提交
17
#include "shellInt.h"
H
hzcheng 已提交
18

19 20 21 22 23
#define LEFT  1
#define RIGHT 2
#define UP    3
#define DOWN  4
#define PSIZE shell.info.promptSize
wafwerar's avatar
wafwerar 已提交
24
#define SHELL_INPUT_MAX_COMMAND_SIZE 10000
S
Shengliang Guan 已提交
25

H
hzcheng 已提交
26
typedef struct {
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
  char    *buffer;
  char    *command;
  uint32_t commandSize;
  uint32_t bufferSize;
  uint32_t cursorOffset;
  uint32_t screenOffset;
  uint32_t endOffset;
} SShellCmd;

static int32_t shellCountPrefixOnes(uint8_t c);
static void    shellGetPrevCharSize(const char *str, int32_t pos, int32_t *size, int32_t *width);
static void    shellGetNextCharSize(const char *str, int32_t pos, int32_t *size, int32_t *width);
static void    shellInsertChar(SShellCmd *cmd, char *c, int size);
static void    shellBackspaceChar(SShellCmd *cmd);
static void    shellClearLineBefore(SShellCmd *cmd);
static void    shellClearLineAfter(SShellCmd *cmd);
static void    shellDeleteChar(SShellCmd *cmd);
static void    shellMoveCursorLeft(SShellCmd *cmd);
static void    shellMoveCursorRight(SShellCmd *cmd);
static void    shellPositionCursorHome(SShellCmd *cmd);
static void    shellPositionCursorEnd(SShellCmd *cmd);
static void    shellPrintChar(char c, int32_t times);
static void    shellPositionCursor(int32_t step, int32_t direction);
static void    shellUpdateBuffer(SShellCmd *cmd);
static int32_t shellIsReadyGo(SShellCmd *cmd);
static void    shellGetMbSizeInfo(const char *str, int32_t *size, int32_t *width);
static void    shellResetCommand(SShellCmd *cmd, const char s[]);
static void    shellClearScreen(int32_t ecmd_pos, int32_t cursor_pos);
static void    shellShowOnScreen(SShellCmd *cmd);

int32_t shellCountPrefixOnes(uint8_t c) {
  uint8_t mask = 127;
H
hzcheng 已提交
59
  mask = ~mask;
60
  int32_t ret = 0;
H
hzcheng 已提交
61 62 63 64 65 66 67 68
  while ((c & mask) != 0) {
    ret++;
    c <<= 1;
  }

  return ret;
}

69
void shellGetPrevCharSize(const char *str, int32_t pos, int32_t *size, int32_t *width) {
H
hzcheng 已提交
70 71
  assert(pos > 0);

wafwerar's avatar
wafwerar 已提交
72
  TdWchar wc;
H
hzcheng 已提交
73 74 75 76 77 78
  *size = 0;
  *width = 0;

  while (--pos >= 0) {
    *size += 1;

79
    if (str[pos] > 0 || shellCountPrefixOnes((uint8_t)str[pos]) > 1) break;
H
hzcheng 已提交
80 81
  }

wmmhello's avatar
wmmhello 已提交
82 83
  taosMbToWchar(&wc, str + pos, MB_CUR_MAX);
  // assert(rc == *size); // it will be core, if str is encode by utf8 and taos charset is gbk
H
hzcheng 已提交
84

wafwerar's avatar
wafwerar 已提交
85
  *width = taosWcharWidth(wc);
H
hzcheng 已提交
86 87
}

88
void shellGetNextCharSize(const char *str, int32_t pos, int32_t *size, int32_t *width) {
H
hzcheng 已提交
89 90
  assert(pos >= 0);

wafwerar's avatar
wafwerar 已提交
91 92 93
  TdWchar wc;
  *size = taosMbToWchar(&wc, str + pos, MB_CUR_MAX);
  *width = taosWcharWidth(wc);
H
hzcheng 已提交
94 95
}

96
void shellInsertChar(SShellCmd *cmd, char *c, int32_t size) {
H
hzcheng 已提交
97 98
  assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset);

wafwerar's avatar
wafwerar 已提交
99 100
  TdWchar wc;
  if (taosMbToWchar(&wc, c, size) < 0) return;
H
hzcheng 已提交
101

102
  shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE);
H
hzcheng 已提交
103 104 105 106 107 108 109
  /* update the buffer */
  memmove(cmd->command + cmd->cursorOffset + size, cmd->command + cmd->cursorOffset,
          cmd->commandSize - cmd->cursorOffset);
  memcpy(cmd->command + cmd->cursorOffset, c, size);
  /* update the values */
  cmd->commandSize += size;
  cmd->cursorOffset += size;
wafwerar's avatar
wafwerar 已提交
110 111
  cmd->screenOffset += taosWcharWidth(wc);
  cmd->endOffset += taosWcharWidth(wc);
112 113
#ifdef WINDOWS
#else
114
  shellShowOnScreen(cmd);
115
#endif
H
hzcheng 已提交
116 117
}

118
void shellBackspaceChar(SShellCmd *cmd) {
H
hzcheng 已提交
119 120 121
  assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset);

  if (cmd->cursorOffset > 0) {
122 123 124 125
    shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE);
    int32_t size = 0;
    int32_t width = 0;
    shellGetPrevCharSize(cmd->command, cmd->cursorOffset, &size, &width);
H
hzcheng 已提交
126 127 128 129 130 131
    memmove(cmd->command + cmd->cursorOffset - size, cmd->command + cmd->cursorOffset,
            cmd->commandSize - cmd->cursorOffset);
    cmd->commandSize -= size;
    cmd->cursorOffset -= size;
    cmd->screenOffset -= width;
    cmd->endOffset -= width;
132
    shellShowOnScreen(cmd);
H
hzcheng 已提交
133 134 135
  }
}

136
void shellClearLineBefore(SShellCmd *cmd) {
137 138
  assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset);

139
  shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE);
S
Shengliang Guan 已提交
140
  memmove(cmd->command, cmd->command + cmd->cursorOffset, cmd->commandSize - cmd->cursorOffset);
141 142 143 144
  cmd->commandSize -= cmd->cursorOffset;
  cmd->cursorOffset = 0;
  cmd->screenOffset = 0;
  cmd->endOffset = cmd->commandSize;
145
  shellShowOnScreen(cmd);
146 147
}

148
void shellClearLineAfter(SShellCmd *cmd) {
149 150
  assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset);

151
  shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE);
152 153
  cmd->commandSize -= cmd->endOffset - cmd->cursorOffset;
  cmd->endOffset = cmd->cursorOffset;
154
  shellShowOnScreen(cmd);
155 156
}

157
void shellDeleteChar(SShellCmd *cmd) {
H
hzcheng 已提交
158 159 160
  assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset);

  if (cmd->cursorOffset < cmd->commandSize) {
161 162 163 164
    shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE);
    int32_t size = 0;
    int32_t width = 0;
    shellGetNextCharSize(cmd->command, cmd->cursorOffset, &size, &width);
H
hzcheng 已提交
165 166 167 168
    memmove(cmd->command + cmd->cursorOffset, cmd->command + cmd->cursorOffset + size,
            cmd->commandSize - cmd->cursorOffset - size);
    cmd->commandSize -= size;
    cmd->endOffset -= width;
169
    shellShowOnScreen(cmd);
H
hzcheng 已提交
170 171 172
  }
}

173
void shellMoveCursorLeft(SShellCmd *cmd) {
H
hzcheng 已提交
174 175 176
  assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset);

  if (cmd->cursorOffset > 0) {
177 178 179 180
    shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE);
    int32_t size = 0;
    int32_t width = 0;
    shellGetPrevCharSize(cmd->command, cmd->cursorOffset, &size, &width);
H
hzcheng 已提交
181 182
    cmd->cursorOffset -= size;
    cmd->screenOffset -= width;
183
    shellShowOnScreen(cmd);
H
hzcheng 已提交
184 185 186
  }
}

187
void shellMoveCursorRight(SShellCmd *cmd) {
H
hzcheng 已提交
188 189 190
  assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset);

  if (cmd->cursorOffset < cmd->commandSize) {
191 192 193 194
    shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE);
    int32_t size = 0;
    int32_t width = 0;
    shellGetNextCharSize(cmd->command, cmd->cursorOffset, &size, &width);
H
hzcheng 已提交
195 196
    cmd->cursorOffset += size;
    cmd->screenOffset += width;
197
    shellShowOnScreen(cmd);
H
hzcheng 已提交
198 199 200
  }
}

201
void shellPositionCursorHome(SShellCmd *cmd) {
H
hzcheng 已提交
202 203 204
  assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset);

  if (cmd->cursorOffset > 0) {
205
    shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE);
H
hzcheng 已提交
206 207
    cmd->cursorOffset = 0;
    cmd->screenOffset = 0;
208
    shellShowOnScreen(cmd);
H
hzcheng 已提交
209 210 211
  }
}

212
void shellPositionCursorEnd(SShellCmd *cmd) {
H
hzcheng 已提交
213 214 215
  assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset);

  if (cmd->cursorOffset < cmd->commandSize) {
216
    shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE);
H
hzcheng 已提交
217 218
    cmd->cursorOffset = cmd->commandSize;
    cmd->screenOffset = cmd->endOffset;
219
    shellShowOnScreen(cmd);
H
hzcheng 已提交
220 221 222
  }
}

223 224
void shellPrintChar(char c, int32_t times) {
  for (int32_t i = 0; i < times; i++) {
H
hzcheng 已提交
225 226 227 228 229
    fprintf(stdout, "%c", c);
  }
  fflush(stdout);
}

230
void shellPositionCursor(int32_t step, int32_t direction) {
wafwerar's avatar
wafwerar 已提交
231
#ifndef WINDOWS
H
hzcheng 已提交
232 233 234 235 236 237 238 239 240 241 242 243
  if (step > 0) {
    if (direction == LEFT) {
      fprintf(stdout, "\033[%dD", step);
    } else if (direction == RIGHT) {
      fprintf(stdout, "\033[%dC", step);
    } else if (direction == UP) {
      fprintf(stdout, "\033[%dA", step);
    } else if (direction == DOWN) {
      fprintf(stdout, "\033[%dB", step);
    }
    fflush(stdout);
  }
wafwerar's avatar
wafwerar 已提交
244
#endif
H
hzcheng 已提交
245 246
}

247
void shellUpdateBuffer(SShellCmd *cmd) {
H
hzcheng 已提交
248 249
  assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset);

250
  if (shellRegexMatch(cmd->buffer, "(\\s+$)|(^$)", REG_EXTENDED)) strcat(cmd->command, " ");
H
hzcheng 已提交
251 252 253
  strcat(cmd->buffer, cmd->command);
  cmd->bufferSize += cmd->commandSize;

254
  memset(cmd->command, 0, SHELL_MAX_COMMAND_SIZE);
H
hzcheng 已提交
255 256 257 258
  cmd->cursorOffset = 0;
  cmd->screenOffset = 0;
  cmd->commandSize = 0;
  cmd->endOffset = 0;
259
  shellShowOnScreen(cmd);
H
hzcheng 已提交
260 261
}

262
int32_t shellIsReadyGo(SShellCmd *cmd) {
H
hzcheng 已提交
263 264
  assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset);

265 266
  char *total = (char *)taosMemoryCalloc(1, SHELL_MAX_COMMAND_SIZE);
  memset(cmd->command + cmd->commandSize, 0, SHELL_MAX_COMMAND_SIZE - cmd->commandSize);
H
hzcheng 已提交
267 268 269
  sprintf(total, "%s%s", cmd->buffer, cmd->command);

  char *reg_str =
S
Shengliang Guan 已提交
270 271
      "(^.*;\\s*$)|(^\\s*$)|(^\\s*exit\\s*$)|(^\\s*q\\s*$)|(^\\s*quit\\s*$)|(^"
      "\\s*clear\\s*$)";
272
  if (shellRegexMatch(total, reg_str, REG_EXTENDED | REG_ICASE)) {
wafwerar's avatar
wafwerar 已提交
273
    taosMemoryFree(total);
H
hzcheng 已提交
274 275 276
    return 1;
  }

wafwerar's avatar
wafwerar 已提交
277
  taosMemoryFree(total);
H
hzcheng 已提交
278 279 280
  return 0;
}

281 282
void shellGetMbSizeInfo(const char *str, int32_t *size, int32_t *width) {
  TdWchar *wc = (TdWchar *)taosMemoryCalloc(sizeof(TdWchar), SHELL_MAX_COMMAND_SIZE);
H
hzcheng 已提交
283
  *size = strlen(str);
284 285
  taosMbsToWchars(wc, str, SHELL_MAX_COMMAND_SIZE);
  *width = taosWcharsWidth(wc, SHELL_MAX_COMMAND_SIZE);
wafwerar's avatar
wafwerar 已提交
286
  taosMemoryFree(wc);
H
hzcheng 已提交
287 288
}

289
void shellResetCommand(SShellCmd *cmd, const char s[]) {
H
hzcheng 已提交
290 291
  assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset);

292 293 294 295 296 297 298
  shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE);
  memset(cmd->buffer, 0, SHELL_MAX_COMMAND_SIZE);
  memset(cmd->command, 0, SHELL_MAX_COMMAND_SIZE);
  strncpy(cmd->command, s, SHELL_MAX_COMMAND_SIZE);
  int32_t size = 0;
  int32_t width = 0;
  shellGetMbSizeInfo(s, &size, &width);
H
hzcheng 已提交
299 300 301 302 303
  cmd->bufferSize = 0;
  cmd->commandSize = size;
  cmd->cursorOffset = size;
  cmd->screenOffset = width;
  cmd->endOffset = width;
304
  shellShowOnScreen(cmd);
H
hzcheng 已提交
305
}
306

307 308 309 310 311 312 313 314

void shellGetScreenSize(int32_t *ws_col, int32_t *ws_row) {
#ifdef WINDOWS
  CONSOLE_SCREEN_BUFFER_INFO csbi;
  GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
  if (ws_col != NULL) *ws_col = csbi.srWindow.Right - csbi.srWindow.Left + 1;
  if (ws_row != NULL) *ws_row = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
#else
315 316
  struct winsize w;
  if (ioctl(0, TIOCGWINSZ, &w) < 0 || w.ws_col == 0 || w.ws_row == 0) {
wafwerar's avatar
wafwerar 已提交
317
    // fprintf(stderr, "No stream device, and use default value(col 120, row 30)\r\n");
318 319 320 321 322
    if (ws_col != NULL) *ws_col = 120;
    if (ws_row != NULL) *ws_row = 30;
  } else {
    if (ws_col != NULL) *ws_col = w.ws_col;
    if (ws_row != NULL) *ws_row = w.ws_row;
323
  }
324 325 326 327 328 329
#endif
}

void shellClearScreen(int32_t ecmd_pos, int32_t cursor_pos) {
  int32_t ws_col;
  shellGetScreenSize(&ws_col, NULL);
330

331 332 333
  int32_t cursor_x = cursor_pos / ws_col;
  int32_t cursor_y = cursor_pos % ws_col;
  int32_t command_x = ecmd_pos / ws_col;
334 335
  shellPositionCursor(cursor_y, LEFT);
  shellPositionCursor(command_x - cursor_x, DOWN);
wafwerar's avatar
wafwerar 已提交
336
#ifndef WINDOWS
337
  fprintf(stdout, "\033[2K");
wafwerar's avatar
wafwerar 已提交
338
#endif
339 340
  for (int32_t i = 0; i < command_x; i++) {
    shellPositionCursor(1, UP);
wafwerar's avatar
wafwerar 已提交
341
  #ifndef WINDOWS
342
    fprintf(stdout, "\033[2K");
wafwerar's avatar
wafwerar 已提交
343
  #endif
344 345
  }
  fflush(stdout);
H
hzcheng 已提交
346
}
347 348

void shellShowOnScreen(SShellCmd *cmd) {
349 350
  int32_t ws_col;
  shellGetScreenSize(&ws_col, NULL);
351 352 353 354 355 356 357 358 359 360 361 362

  TdWchar wc;
  int32_t size = 0;

  // Print out the command.
  char *total_string = taosMemoryMalloc(SHELL_MAX_COMMAND_SIZE);
  memset(total_string, '\0', SHELL_MAX_COMMAND_SIZE);
  if (strcmp(cmd->buffer, "") == 0) {
    sprintf(total_string, "%s%s", shell.info.promptHeader, cmd->command);
  } else {
    sprintf(total_string, "%s%s", shell.info.promptContinue, cmd->command);
  }
363
  int32_t remain_column = ws_col;
364 365 366 367 368 369 370 371 372 373 374 375
  for (char *str = total_string; size < cmd->commandSize + PSIZE;) {
    int32_t ret = taosMbToWchar(&wc, str, MB_CUR_MAX);
    if (ret < 0) break;
    size += ret;
    /* assert(size >= 0); */
    int32_t width = taosWcharWidth(wc);
    if (remain_column > width) {
      printf("%lc", wc);
      remain_column -= width;
    } else {
      if (remain_column == width) {
        printf("%lc\n\r", wc);
376
        remain_column = ws_col;
377 378
      } else {
        printf("\n\r%lc", wc);
379
        remain_column = ws_col - width;
380 381 382 383 384 385 386 387 388 389 390
      }
    }

    str = total_string + size;
  }

  taosMemoryFree(total_string);
  // Position the cursor
  int32_t cursor_pos = cmd->screenOffset + PSIZE;
  int32_t ecmd_pos = cmd->endOffset + PSIZE;

391 392 393 394 395 396
  int32_t cursor_x = cursor_pos / ws_col;
  int32_t cursor_y = cursor_pos % ws_col;
  // int32_t cursor_y = cursor % ws_col;
  int32_t command_x = ecmd_pos / ws_col;
  int32_t command_y = ecmd_pos % ws_col;
  // int32_t command_y = (command.size() + PSIZE) % ws_col;
397 398 399 400 401 402 403
  shellPositionCursor(command_y, LEFT);
  shellPositionCursor(command_x, UP);
  shellPositionCursor(cursor_x, DOWN);
  shellPositionCursor(cursor_y, RIGHT);
  fflush(stdout);
}

wafwerar's avatar
wafwerar 已提交
404 405 406 407 408 409 410 411 412 413
char taosGetConsoleChar() {
#ifdef WINDOWS
  static void *console = NULL;
  if (console == NULL) {
    console = GetStdHandle(STD_INPUT_HANDLE);
  }
  static TdWchar buf[SHELL_INPUT_MAX_COMMAND_SIZE];
  static char mbStr[5];
  static unsigned long bufLen = 0;
  static uint16_t bufIndex = 0, mbStrIndex = 0, mbStrLen = 0;
wafwerar's avatar
wafwerar 已提交
414
  while (bufLen == 0) {
wafwerar's avatar
wafwerar 已提交
415
    ReadConsoleW(console, buf, SHELL_INPUT_MAX_COMMAND_SIZE, &bufLen, NULL);
wafwerar's avatar
wafwerar 已提交
416
    if (bufLen > 0 && buf[0] == 0) bufLen = 0;
wafwerar's avatar
wafwerar 已提交
417 418 419
    bufIndex = 0;
  }
  if (mbStrLen == 0){
wafwerar's avatar
wafwerar 已提交
420 421 422
    if (buf[bufIndex] == '\r') {
      bufIndex++;
    }
wafwerar's avatar
wafwerar 已提交
423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439
    mbStrLen = WideCharToMultiByte(CP_UTF8, 0, &buf[bufIndex], 1, mbStr, sizeof(mbStr), NULL, NULL);
    mbStrIndex = 0;
    bufIndex++;
  }
  mbStrIndex++;
  if (mbStrIndex == mbStrLen) {
    mbStrLen = 0;
    if (bufIndex == bufLen) {
      bufLen = 0;
    }
  }
  return mbStr[mbStrIndex-1];
#else
  return (char)getchar();  // getchar() return an 'int32_t' value
#endif
}

440 441 442 443 444 445 446 447 448 449 450 451 452
int32_t shellReadCommand(char *command) {
  SShellHistory *pHistory = &shell.history;
  SShellCmd      cmd = {0};
  uint32_t       hist_counter = pHistory->hend;
  char           utf8_array[10] = "\0";

  cmd.buffer = (char *)taosMemoryCalloc(1, SHELL_MAX_COMMAND_SIZE);
  cmd.command = (char *)taosMemoryCalloc(1, SHELL_MAX_COMMAND_SIZE);
  shellShowOnScreen(&cmd);

  // Read input.
  char c;
  while (1) {
wafwerar's avatar
wafwerar 已提交
453
    c = taosGetConsoleChar();
454 455 456 457 458 459 460 461 462

    if (c == EOF) {
      return c;
    }

    if (c < 0) {  // For UTF-8
      int32_t count = shellCountPrefixOnes(c);
      utf8_array[0] = c;
      for (int32_t k = 1; k < count; k++) {
wafwerar's avatar
wafwerar 已提交
463
        c = taosGetConsoleChar();
464 465 466 467 468 469
        utf8_array[k] = c;
      }
      shellInsertChar(&cmd, utf8_array, count);
    } else if (c < '\033') {
      // Ctrl keys.  TODO: Implement ctrl combinations
      switch (c) {
wafwerar's avatar
wafwerar 已提交
470 471
        case 0:
          break;
472 473 474 475
        case 1:  // ctrl A
          shellPositionCursorHome(&cmd);
          break;
        case 3:
wafwerar's avatar
wafwerar 已提交
476
          printf("\r\n");
477
          shellResetCommand(&cmd, "");
478 479 480 481 482
          #ifdef WINDOWS
            raise(SIGINT);
          #else
            kill(0, SIGINT);
          #endif
483 484
          break;
        case 4:  // EOF or Ctrl+D
wafwerar's avatar
wafwerar 已提交
485
          taosResetTerminalMode();
wafwerar's avatar
wafwerar 已提交
486
          printf("\r\n");
487 488 489 490 491 492 493 494 495
          return -1;
        case 5:  // ctrl E
          shellPositionCursorEnd(&cmd);
          break;
        case 8:
          shellBackspaceChar(&cmd);
          break;
        case '\n':
        case '\r':
496 497
        #ifdef WINDOWS 
        #else
wafwerar's avatar
wafwerar 已提交
498
          printf("\r\n");
499
        #endif
500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520
          if (shellIsReadyGo(&cmd)) {
            sprintf(command, "%s%s", cmd.buffer, cmd.command);
            taosMemoryFreeClear(cmd.buffer);
            taosMemoryFreeClear(cmd.command);
            return 0;
          } else {
            shellUpdateBuffer(&cmd);
          }
          break;
        case 11:  // Ctrl + K;
          shellClearLineAfter(&cmd);
          break;
        case 12:  // Ctrl + L;
          system("clear");
          shellShowOnScreen(&cmd);
          break;
        case 21:  // Ctrl + U;
          shellClearLineBefore(&cmd);
          break;
      }
    } else if (c == '\033') {
wafwerar's avatar
wafwerar 已提交
521
      c = taosGetConsoleChar();
522 523
      switch (c) {
        case '[':
wafwerar's avatar
wafwerar 已提交
524
          c = taosGetConsoleChar();
525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550
          switch (c) {
            case 'A':  // Up arrow
              if (hist_counter != pHistory->hstart) {
                hist_counter = (hist_counter + SHELL_MAX_HISTORY_SIZE - 1) % SHELL_MAX_HISTORY_SIZE;
                shellResetCommand(&cmd, (pHistory->hist[hist_counter] == NULL) ? "" : pHistory->hist[hist_counter]);
              }
              break;
            case 'B':  // Down arrow
              if (hist_counter != pHistory->hend) {
                int32_t next_hist = (hist_counter + 1) % SHELL_MAX_HISTORY_SIZE;

                if (next_hist != pHistory->hend) {
                  shellResetCommand(&cmd, (pHistory->hist[next_hist] == NULL) ? "" : pHistory->hist[next_hist]);
                } else {
                  shellResetCommand(&cmd, "");
                }
                hist_counter = next_hist;
              }
              break;
            case 'C':  // Right arrow
              shellMoveCursorRight(&cmd);
              break;
            case 'D':  // Left arrow
              shellMoveCursorLeft(&cmd);
              break;
            case '1':
wafwerar's avatar
wafwerar 已提交
551
              if ((c = taosGetConsoleChar()) == '~') {
552 553 554 555 556
                // Home key
                shellPositionCursorHome(&cmd);
              }
              break;
            case '2':
wafwerar's avatar
wafwerar 已提交
557
              if ((c = taosGetConsoleChar()) == '~') {
558 559 560 561
                // Insert key
              }
              break;
            case '3':
wafwerar's avatar
wafwerar 已提交
562
              if ((c = taosGetConsoleChar()) == '~') {
563 564 565 566 567
                // Delete key
                shellDeleteChar(&cmd);
              }
              break;
            case '4':
wafwerar's avatar
wafwerar 已提交
568
              if ((c = taosGetConsoleChar()) == '~') {
569 570 571 572 573
                // End key
                shellPositionCursorEnd(&cmd);
              }
              break;
            case '5':
wafwerar's avatar
wafwerar 已提交
574
              if ((c = taosGetConsoleChar()) == '~') {
575 576 577 578
                // Page up key
              }
              break;
            case '6':
wafwerar's avatar
wafwerar 已提交
579
              if ((c = taosGetConsoleChar()) == '~') {
580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603
                // Page down key
              }
              break;
            case 72:
              // Home key
              shellPositionCursorHome(&cmd);
              break;
            case 70:
              // End key
              shellPositionCursorEnd(&cmd);
              break;
          }
          break;
      }
    } else if (c == 0x7f) {
      // press delete key
      shellBackspaceChar(&cmd);
    } else {
      shellInsertChar(&cmd, &c, 1);
    }
  }

  return 0;
}