• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

taosdata / TDengine / #3831

02 Apr 2025 01:14AM UTC coverage: 34.081% (-0.02%) from 34.097%
#3831

push

travis-ci

happyguoxy
test:alter gcda dir

148596 of 599532 branches covered (24.79%)

Branch coverage included in aggregate %.

222550 of 489473 relevant lines covered (45.47%)

1589752.67 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

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

16
#define __USE_XOPEN
17
#include "shellInt.h"
18
#include "shellAuto.h"
19

20
#define LEFT  1
21
#define RIGHT 2
22
#define UP    3
23
#define DOWN  4
24
#define PSIZE shell.info.promptSize
25
#define SHELL_INPUT_MAX_COMMAND_SIZE 10000
26

27

28
static int32_t shellCountPrefixOnes(uint8_t c);
29

30
static void    shellGetNextCharSize(const char *str, int32_t pos, int32_t *size, int32_t *width);
31

32
static void    shellBackspaceChar(SShellCmd *cmd);
33
static void    shellClearLineBefore(SShellCmd *cmd);
34
static void    shellClearLineAfter(SShellCmd *cmd);
35
static void    shellDeleteChar(SShellCmd *cmd);
36
static void    shellMoveCursorLeft(SShellCmd *cmd);
37
static void    shellMoveCursorRight(SShellCmd *cmd);
38
static void    shellPositionCursorHome(SShellCmd *cmd);
39
static void    shellPositionCursorEnd(SShellCmd *cmd);
40
static void    shellPrintChar(char c, int32_t times);
41
static void    shellPositionCursor(int32_t step, int32_t direction);
42
static void    shellUpdateBuffer(SShellCmd *cmd);
43
static bool    shellIsReadyGo(SShellCmd *cmd);
44
static void    shellGetMbSizeInfo(const char *str, int32_t *size, int32_t *width);
45
static void    shellResetCommand(SShellCmd *cmd, const char s[]);
46
void           shellClearScreen(int32_t ecmd_pos, int32_t cursor_pos);
47
void           shellShowOnScreen(SShellCmd *cmd);
48
void           shellGetPrevCharSize(const char *str, int32_t pos, int32_t *size, int32_t *width);
49
void           shellInsertChar(SShellCmd *cmd, char *c, int size);
50
void           shellInsertString(SShellCmd *cmd, char *str, int size);
51

52
int32_t shellCountPrefixOnes(uint8_t c) {
×
53
  uint8_t mask = 127;
×
54
  mask = ~mask;
×
55
  int32_t ret = 0;
×
56
  while ((c & mask) != 0) {
×
57
    ret++;
×
58
    c <<= 1;
×
59
  }
60

61
  return ret;
×
62
}
63

64
void shellGetPrevCharSize(const char *str, int32_t pos, int32_t *size, int32_t *width) {
×
65
  if (pos <= 0) return;
×
66

67
  TdWchar wc;
68
  *size = 0;
×
69
  *width = 0;
×
70

71
  while (--pos >= 0) {
×
72
    *size += 1;
×
73

74
    if (str[pos] > 0 || shellCountPrefixOnes((uint8_t)str[pos]) > 1) break;
×
75
  }
76

77
  taosMbToWchar(&wc, str + pos, MB_CUR_MAX);
×
78
  // ASSERT(rc == *size); // it will be core, if str is encode by utf8 and taos charset is gbk
79

80
  *width = taosWcharWidth(wc);
×
81
}
82

83
void shellGetNextCharSize(const char *str, int32_t pos, int32_t *size, int32_t *width) {
×
84
  if(pos < 0) return;
×
85

86
  TdWchar wc;
87
  *size = taosMbToWchar(&wc, str + pos, MB_CUR_MAX);
×
88
  *width = taosWcharWidth(wc);
×
89
}
90

91
void shellInsertChar(SShellCmd *cmd, char *c, int32_t size) {
×
92
  if(cmd->cursorOffset > cmd->commandSize || cmd->endOffset < cmd->screenOffset) return;
×
93

94
  TdWchar wc;
95
  if (taosMbToWchar(&wc, c, size) < 0) return;
×
96

97
  shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE);
×
98
  /* update the buffer */
99
  memmove(cmd->command + cmd->cursorOffset + size, cmd->command + cmd->cursorOffset,
×
100
          cmd->commandSize - cmd->cursorOffset);
×
101
  memcpy(cmd->command + cmd->cursorOffset, c, size);
×
102
  /* update the values */
103
  cmd->commandSize += size;
×
104
  cmd->cursorOffset += size;
×
105
  cmd->screenOffset += taosWcharWidth(wc);
×
106
  cmd->endOffset += taosWcharWidth(wc);
×
107

108
  // set string end
109
  cmd->command[cmd->commandSize] = 0;
×
110
#ifdef WINDOWS
111
#else
112
  shellShowOnScreen(cmd);
×
113
#endif
114
}
115

116
// insert string . count is str char count
117
void shellInsertStr(SShellCmd *cmd, char *str, int32_t size) {
×
118
  shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE);
×
119
  /* update the buffer */
120
  memmove(cmd->command + cmd->cursorOffset + size, cmd->command + cmd->cursorOffset,
×
121
          cmd->commandSize - cmd->cursorOffset);
×
122
  memcpy(cmd->command + cmd->cursorOffset, str, size);
×
123
  /* update the values */
124
  cmd->commandSize += size;
×
125
  cmd->cursorOffset += size;
×
126
  cmd->screenOffset += size;
×
127
  cmd->endOffset += size;
×
128

129
  // set string end
130
  cmd->command[cmd->commandSize] = 0;
×
131
#ifdef WINDOWS
132
#else
133
  shellShowOnScreen(cmd);
×
134
#endif
135
}
×
136

137
void shellBackspaceChar(SShellCmd *cmd) {
×
138
  if(cmd->cursorOffset > cmd->commandSize || cmd->endOffset < cmd->screenOffset) return;
×
139

140
  if (cmd->cursorOffset > 0) {
×
141
    shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE);
×
142
    int32_t size = 0;
×
143
    int32_t width = 0;
×
144
    shellGetPrevCharSize(cmd->command, cmd->cursorOffset, &size, &width);
×
145
    memmove(cmd->command + cmd->cursorOffset - size, cmd->command + cmd->cursorOffset,
×
146
            cmd->commandSize - cmd->cursorOffset);
×
147
    cmd->commandSize -= size;
×
148
    cmd->cursorOffset -= size;
×
149
    cmd->screenOffset -= width;
×
150
    cmd->endOffset -= width;
×
151
    // set string end
152
    cmd->command[cmd->commandSize] = 0;
×
153
    shellShowOnScreen(cmd);
×
154
  }
155
}
156

157
void shellClearLineBefore(SShellCmd *cmd) {
×
158
  if(cmd->cursorOffset > cmd->commandSize || cmd->endOffset < cmd->screenOffset) return;
×
159

160
  shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE);
×
161
  memmove(cmd->command, cmd->command + cmd->cursorOffset, cmd->commandSize - cmd->cursorOffset);
×
162
  cmd->commandSize -= cmd->cursorOffset;
×
163
  cmd->cursorOffset = 0;
×
164
  cmd->screenOffset = 0;
×
165
  cmd->endOffset = cmd->commandSize;
×
166
  // set string end
167
  cmd->command[cmd->commandSize] = 0;
×
168
  shellShowOnScreen(cmd);
×
169
}
170

171
void shellClearLineAfter(SShellCmd *cmd) {
×
172
  if(cmd->cursorOffset > cmd->commandSize || cmd->endOffset < cmd->screenOffset) return;
×
173

174
  shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE);
×
175
  cmd->commandSize -= cmd->endOffset - cmd->cursorOffset;
×
176
  cmd->endOffset = cmd->cursorOffset;
×
177
  shellShowOnScreen(cmd);
×
178
}
179

180
void shellDeleteChar(SShellCmd *cmd) {
×
181
  if(cmd->cursorOffset > cmd->commandSize || cmd->endOffset < cmd->screenOffset) return;
×
182

183
  if (cmd->cursorOffset < cmd->commandSize) {
×
184
    shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE);
×
185
    int32_t size = 0;
×
186
    int32_t width = 0;
×
187
    shellGetNextCharSize(cmd->command, cmd->cursorOffset, &size, &width);
×
188
    memmove(cmd->command + cmd->cursorOffset, cmd->command + cmd->cursorOffset + size,
×
189
            cmd->commandSize - cmd->cursorOffset - size);
×
190
    cmd->commandSize -= size;
×
191
    cmd->endOffset -= width;
×
192
    // set string end
193
    cmd->command[cmd->commandSize] = 0;
×
194
    shellShowOnScreen(cmd);
×
195
  }
196
}
197

198
void shellMoveCursorLeft(SShellCmd *cmd) {
×
199
  if(cmd->cursorOffset > cmd->commandSize || cmd->endOffset < cmd->screenOffset) return;
×
200

201
  if (cmd->cursorOffset > 0) {
×
202
    shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE);
×
203
    int32_t size = 0;
×
204
    int32_t width = 0;
×
205
    shellGetPrevCharSize(cmd->command, cmd->cursorOffset, &size, &width);
×
206
    cmd->cursorOffset -= size;
×
207
    cmd->screenOffset -= width;
×
208
    shellShowOnScreen(cmd);
×
209
  }
210
}
211

212
void shellMoveCursorRight(SShellCmd *cmd) {
×
213
  if(cmd->cursorOffset > cmd->commandSize || cmd->endOffset < cmd->screenOffset) return;
×
214

215
  if (cmd->cursorOffset < cmd->commandSize) {
×
216
    shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE);
×
217
    int32_t size = 0;
×
218
    int32_t width = 0;
×
219
    shellGetNextCharSize(cmd->command, cmd->cursorOffset, &size, &width);
×
220
    cmd->cursorOffset += size;
×
221
    cmd->screenOffset += width;
×
222
    shellShowOnScreen(cmd);
×
223
  }
224
}
225

226
void shellPositionCursorHome(SShellCmd *cmd) {
×
227
  if(cmd->cursorOffset > cmd->commandSize || cmd->endOffset < cmd->screenOffset) return;
×
228

229
  if (cmd->cursorOffset > 0) {
×
230
    shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE);
×
231
    cmd->cursorOffset = 0;
×
232
    cmd->screenOffset = 0;
×
233
    shellShowOnScreen(cmd);
×
234
  }
235
}
236

237
void positionCursorMiddle(SShellCmd *cmd) {
×
238
  if (cmd->endOffset > 0) {
×
239
    shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE);
×
240
    cmd->cursorOffset = cmd->commandSize/2;
×
241
    cmd->screenOffset = cmd->endOffset/2;
×
242
    shellShowOnScreen(cmd);
×
243
  }
244
}
×
245

246
void shellPositionCursorEnd(SShellCmd *cmd) {
×
247
  if(cmd->cursorOffset > cmd->commandSize || cmd->endOffset < cmd->screenOffset) return;
×
248

249
  if (cmd->cursorOffset < cmd->commandSize) {
×
250
    shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE);
×
251
    cmd->cursorOffset = cmd->commandSize;
×
252
    cmd->screenOffset = cmd->endOffset;
×
253
    shellShowOnScreen(cmd);
×
254
  }
255
}
256

257
void shellPrintChar(char c, int32_t times) {
×
258
  for (int32_t i = 0; i < times; i++) {
×
259
    fprintf(stdout, "%c", c);
×
260
  }
261
  fflush(stdout);
×
262
}
×
263

264
void shellPositionCursor(int32_t step, int32_t direction) {
×
265
#ifndef WINDOWS
266
  if (step > 0) {
×
267
    if (direction == LEFT) {
×
268
      fprintf(stdout, "\033[%dD", step);
×
269
    } else if (direction == RIGHT) {
×
270
      fprintf(stdout, "\033[%dC", step);
×
271
    } else if (direction == UP) {
×
272
      fprintf(stdout, "\033[%dA", step);
×
273
    } else if (direction == DOWN) {
×
274
      fprintf(stdout, "\033[%dB", step);
×
275
    }
276
    fflush(stdout);
×
277
  }
278
#endif
279
}
×
280

281
void shellUpdateBuffer(SShellCmd *cmd) {
×
282
  if(cmd->cursorOffset > cmd->commandSize || cmd->endOffset < cmd->screenOffset) return;
×
283

284
  if (shellRegexMatch(cmd->buffer, "(\\s+$)|(^$)", REG_EXTENDED)) strcat(cmd->command, " ");
×
285
  strcat(cmd->buffer, cmd->command);
×
286
  cmd->bufferSize += cmd->commandSize;
×
287

288
  memset(cmd->command, 0, SHELL_MAX_COMMAND_SIZE);
×
289
  cmd->cursorOffset = 0;
×
290
  cmd->screenOffset = 0;
×
291
  cmd->commandSize = 0;
×
292
  cmd->endOffset = 0;
×
293
  shellShowOnScreen(cmd);
×
294
}
295

296
bool shellIsReadyGo(SShellCmd *cmd) {
×
297
  if(cmd->cursorOffset > cmd->commandSize || cmd->endOffset < cmd->screenOffset) return false;
×
298

299
  char *total = (char *)taosMemoryCalloc(1, SHELL_MAX_COMMAND_SIZE);
×
300
  memset(cmd->command + cmd->commandSize, 0, SHELL_MAX_COMMAND_SIZE - cmd->commandSize);
×
301
  sprintf(total, "%s%s", cmd->buffer, cmd->command);
×
302

303
  char *reg_str =
×
304
      "(^.*;\\s*$)|(^\\s*$)|(^\\s*exit\\s*$)|(^\\s*q\\s*$)|(^\\s*quit\\s*$)|(^"
305
      "\\s*clear\\s*$)";
306
  if (shellRegexMatch(total, reg_str, REG_EXTENDED | REG_ICASE)) {
×
307
    taosMemoryFree(total);
×
308
    return true;
×
309
  }
310

311
  taosMemoryFree(total);
×
312
  return false;
×
313
}
314

315
void shellGetMbSizeInfo(const char *str, int32_t *size, int32_t *width) {
×
316
  TdWchar *wc = (TdWchar *)taosMemoryCalloc(sizeof(TdWchar), SHELL_MAX_COMMAND_SIZE);
×
317
  *size = strlen(str);
×
318
  taosMbsToWchars(wc, str, SHELL_MAX_COMMAND_SIZE);
×
319
  *width = taosWcharsWidth(wc, SHELL_MAX_COMMAND_SIZE);
×
320
  taosMemoryFree(wc);
×
321
}
×
322

323
void shellResetCommand(SShellCmd *cmd, const char s[]) {
×
324
  if(cmd->cursorOffset > cmd->commandSize || cmd->endOffset < cmd->screenOffset) return;
×
325

326
  shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE);
×
327
  memset(cmd->buffer, 0, SHELL_MAX_COMMAND_SIZE);
×
328
  memset(cmd->command, 0, SHELL_MAX_COMMAND_SIZE);
×
329
  strncpy(cmd->command, s, SHELL_MAX_COMMAND_SIZE);
×
330
  int32_t size = 0;
×
331
  int32_t width = 0;
×
332
  shellGetMbSizeInfo(s, &size, &width);
×
333
  cmd->bufferSize = 0;
×
334
  cmd->commandSize = size;
×
335
  cmd->cursorOffset = size;
×
336
  cmd->screenOffset = width;
×
337
  cmd->endOffset = width;
×
338
  shellShowOnScreen(cmd);
×
339
}
340

341

342
void shellGetScreenSize(int32_t *ws_col, int32_t *ws_row) {
×
343
#ifdef WINDOWS
344
  CONSOLE_SCREEN_BUFFER_INFO csbi;
345
  GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
346
  if (ws_col != NULL) *ws_col = csbi.srWindow.Right - csbi.srWindow.Left + 1;
347
  if (ws_row != NULL) *ws_row = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
348
#elif defined(TD_ASTRA)
349
  if (ws_col != NULL) *ws_col = 120;
350
  if (ws_row != NULL) *ws_row = 30;
351
#else
352
  struct winsize w;
353
  if (ioctl(0, TIOCGWINSZ, &w) < 0 || w.ws_col == 0 || w.ws_row == 0) {
×
354
    // fprintf(stderr, "No stream device, and use default value(col 120, row 30)\r\n");
355
    if (ws_col != NULL) *ws_col = 120;
×
356
    if (ws_row != NULL) *ws_row = 30;
×
357
  } else {
358
    if (ws_col != NULL) *ws_col = w.ws_col;
×
359
    if (ws_row != NULL) *ws_row = w.ws_row;
×
360
  }
361
#endif
362
}
×
363

364
void shellClearScreen(int32_t ecmd_pos, int32_t cursor_pos) {
×
365
  int32_t ws_col;
366
  shellGetScreenSize(&ws_col, NULL);
×
367

368
  int32_t cursor_x = cursor_pos / ws_col;
×
369
  int32_t cursor_y = cursor_pos % ws_col;
×
370
  int32_t command_x = ecmd_pos / ws_col;
×
371
  shellPositionCursor(cursor_y, LEFT);
×
372
  shellPositionCursor(command_x - cursor_x, DOWN);
×
373
#ifndef WINDOWS
374
  fprintf(stdout, "\033[2K");
×
375
#endif
376
  for (int32_t i = 0; i < command_x; i++) {
×
377
    shellPositionCursor(1, UP);
×
378
  #ifndef WINDOWS
379
    fprintf(stdout, "\033[2K");
×
380
  #endif
381
  }
382
  fflush(stdout);
×
383
}
×
384

385
void shellShowOnScreen(SShellCmd *cmd) {
×
386
  int32_t ws_col;
387
  shellGetScreenSize(&ws_col, NULL);
×
388

389
  TdWchar wc;
390
  int32_t size = 0;
×
391

392
  // Print out the command.
393
  char *total_string = taosMemoryMalloc(SHELL_MAX_COMMAND_SIZE);
×
394
  memset(total_string, '\0', SHELL_MAX_COMMAND_SIZE);
×
395
  if (strcmp(cmd->buffer, "") == 0) {
×
396
    sprintf(total_string, "%s%s", shell.info.promptHeader, cmd->command);
×
397
  } else {
398
    sprintf(total_string, "%s%s", shell.info.promptContinue, cmd->command);
×
399
  }
400
  int32_t remain_column = ws_col;
×
401
  for (char *str = total_string; size < cmd->commandSize + PSIZE;) {
×
402
    int32_t ret = taosMbToWchar(&wc, str, MB_CUR_MAX);
×
403
    if (ret < 0) break;
×
404
    size += ret;
×
405
    /* ASSERT(size >= 0); */
406
    int32_t width = taosWcharWidth(wc);
×
407
    if (remain_column > width) {
×
408
      printf("%lc", wc);
×
409
      remain_column -= width;
×
410
    } else {
411
      if (remain_column == width) {
×
412
        printf("%lc\n\r", wc);
×
413
        remain_column = ws_col;
×
414
      } else {
415
        printf("\n\r%lc", wc);
×
416
        remain_column = ws_col - width;
×
417
      }
418
    }
419

420
    str = total_string + size;
×
421
  }
422

423
  taosMemoryFree(total_string);
×
424
  // Position the cursor
425
  int32_t cursor_pos = cmd->screenOffset + PSIZE;
×
426
  int32_t ecmd_pos = cmd->endOffset + PSIZE;
×
427

428
  int32_t cursor_x = cursor_pos / ws_col;
×
429
  int32_t cursor_y = cursor_pos % ws_col;
×
430
  // int32_t cursor_y = cursor % ws_col;
431
  int32_t command_x = ecmd_pos / ws_col;
×
432
  int32_t command_y = ecmd_pos % ws_col;
×
433
  // int32_t command_y = (command.size() + PSIZE) % ws_col;
434
  shellPositionCursor(command_y, LEFT);
×
435
  shellPositionCursor(command_x, UP);
×
436
  shellPositionCursor(cursor_x, DOWN);
×
437
  shellPositionCursor(cursor_y, RIGHT);
×
438
  fflush(stdout);
×
439
}
×
440

441
char taosGetConsoleChar() {
×
442
#ifdef WINDOWS
443
  static void *console = NULL;
444
  if (console == NULL) {
445
    console = GetStdHandle(STD_INPUT_HANDLE);
446
  }
447
  static TdWchar buf[SHELL_INPUT_MAX_COMMAND_SIZE];
448
  static char mbStr[5];
449
  static unsigned long bufLen = 0;
450
  static uint16_t bufIndex = 0, mbStrIndex = 0, mbStrLen = 0;
451
  CONSOLE_READCONSOLE_CONTROL inputControl={ sizeof(CONSOLE_READCONSOLE_CONTROL), 0, 0, 0 };
452
  while (bufLen == 0) {
453
    ReadConsoleW(console, buf, SHELL_INPUT_MAX_COMMAND_SIZE, &bufLen, &inputControl);
454
    if (bufLen > 0 && buf[0] == 0) bufLen = 0;
455
    bufIndex = 0;
456
  }
457
  if (mbStrLen == 0){
458
    if (buf[bufIndex] == '\r') {
459
      bufIndex++;
460
    }
461
    mbStrLen = WideCharToMultiByte(CP_UTF8, 0, &buf[bufIndex], 1, mbStr, sizeof(mbStr), NULL, NULL);
462
    mbStrIndex = 0;
463
    bufIndex++;
464
  }
465
  mbStrIndex++;
466
  if (mbStrIndex == mbStrLen) {
467
    mbStrLen = 0;
468
    if (bufIndex == bufLen) {
469
      bufLen = 0;
470
    }
471
  }
472
  return mbStr[mbStrIndex-1];
473
#else
474
  return (char)getchar();  // getchar() return an 'int32_t' value
×
475
#endif
476
}
477

478
int32_t shellReadCommand(char *command) {
×
479
  SShellHistory *pHistory = &shell.history;
×
480
  SShellCmd      cmd = {0};
×
481
  uint32_t       hist_counter = pHistory->hend;
×
482
  char           utf8_array[10] = "\0";
×
483

484
  cmd.buffer = (char *)taosMemoryCalloc(1, SHELL_MAX_COMMAND_SIZE);
×
485
  cmd.command = (char *)taosMemoryCalloc(1, SHELL_MAX_COMMAND_SIZE);
×
486
  shellShowOnScreen(&cmd);
×
487

488
  // Read input.
489
  char c;
490
  while (1) {
491
    c = taosGetConsoleChar();
×
492

493
    if (c == (char)EOF) {
×
494
      taosMemoryFreeClear(cmd.buffer);
×
495
      taosMemoryFreeClear(cmd.command);
×
496
      return c;
×
497
    }
498

499
    if (c < 0) {  // For UTF-8
×
500
      int32_t count = shellCountPrefixOnes(c);
×
501
      utf8_array[0] = c;
×
502
      for (int32_t k = 1; k < count; k++) {
×
503
        c = taosGetConsoleChar();
×
504
        utf8_array[k] = c;
×
505
      }
506
      shellInsertChar(&cmd, utf8_array, count);
×
507
      pressOtherKey(c);
×
508
    } else if (c == TAB_KEY) {
×
509
      // press TAB key
510
      pressTabKey(&cmd);
×
511
    } else if (c < '\033') {
×
512
      pressOtherKey(c);
×
513
      // Ctrl keys.  TODO: Implement ctrl combinations
514
      switch (c) {
×
515
        case 0:
×
516
          break;
×
517
        case 1:  // ctrl A
×
518
          shellPositionCursorHome(&cmd);
×
519
          break;
×
520
        case 3:
×
521
          printf("\r\n");
×
522
          shellResetCommand(&cmd, "");
×
523
          #ifdef WINDOWS
524
            raise(SIGINT);
525
          #else
526
            kill(0, SIGINT);
×
527
          #endif
528
          break;
×
529
        case 4:  // EOF or Ctrl+D
×
530
          taosResetTerminalMode();
×
531
          printf("\r\n");
×
532
          taosMemoryFreeClear(cmd.buffer);
×
533
          taosMemoryFreeClear(cmd.command);
×
534
          return -1;
×
535
        case 5:  // ctrl E
×
536
          shellPositionCursorEnd(&cmd);
×
537
          break;
×
538
        case 8:
×
539
          shellBackspaceChar(&cmd);
×
540
          break;
×
541
        case '\n':
×
542
        case '\r':
543
        #ifdef WINDOWS 
544
        #else
545
          printf("\r\n");
×
546
        #endif
547
          if (shellIsReadyGo(&cmd)) {
×
548
            sprintf(command, "%s%s", cmd.buffer, cmd.command);
×
549
            taosMemoryFreeClear(cmd.buffer);
×
550
            taosMemoryFreeClear(cmd.command);
×
551
            return 0;
×
552
          } else {
553
            shellUpdateBuffer(&cmd);
×
554
          }
555
          break;
×
556
        case 11:  // Ctrl + K;
×
557
          shellClearLineAfter(&cmd);
×
558
          break;
×
559
        case 12:  // Ctrl + L;
×
560
#pragma GCC diagnostic push
561
#pragma GCC diagnostic ignored "-Wunused-result"
562
#ifndef TD_ASTRA
563
          system("clear");
×
564
#else
565
          printf("\033[2J\033[H");
566
#endif
567
#pragma GCC diagnostic pop
568
          shellShowOnScreen(&cmd);
×
569
          break;
×
570
        case 21:  // Ctrl + U;
×
571
          shellClearLineBefore(&cmd);
×
572
          break;
×
573
        case 23:  // Ctrl + W;
×
574
          positionCursorMiddle(&cmd);
×
575
          break;          
×
576
      }
577
    } else if (c == '\033') {
×
578
      pressOtherKey(c);
×
579
      c = taosGetConsoleChar();
×
580
      switch (c) {
×
581
        case '[':
×
582
          c = taosGetConsoleChar();
×
583
          switch (c) {
×
584
            case 'A':  // Up arrow
×
585
              hist_counter = (hist_counter + SHELL_MAX_HISTORY_SIZE - 1) % SHELL_MAX_HISTORY_SIZE;
×
586
              if (pHistory->hist[hist_counter] == NULL) {
×
587
                hist_counter = (hist_counter + SHELL_MAX_HISTORY_SIZE + 1) % SHELL_MAX_HISTORY_SIZE;
×
588
              } else {
589
                shellResetCommand(&cmd, pHistory->hist[hist_counter]);
×
590
              }
591
              break;
×
592
            case 'B':  // Down arrow
×
593
              if (hist_counter != pHistory->hend) {
×
594
                int32_t next_hist = (hist_counter + 1) % SHELL_MAX_HISTORY_SIZE;
×
595

596
                if (next_hist != pHistory->hend) {
×
597
                  shellResetCommand(&cmd, (pHistory->hist[next_hist] == NULL) ? "" : pHistory->hist[next_hist]);
×
598
                } else {
599
                  shellResetCommand(&cmd, "");
×
600
                }
601
                hist_counter = next_hist;
×
602
              }
603
              break;
×
604
            case 'C':  // Right arrow
×
605
              shellMoveCursorRight(&cmd);
×
606
              break;
×
607
            case 'D':  // Left arrow
×
608
              shellMoveCursorLeft(&cmd);
×
609
              break;
×
610
            case '1':
×
611
              if ((c = taosGetConsoleChar()) == '~') {
×
612
                // Home key
613
                shellPositionCursorHome(&cmd);
×
614
              }
615
              break;
×
616
            case '2':
×
617
              if ((c = taosGetConsoleChar()) == '~') {
×
618
                // Insert key
619
              }
620
              break;
×
621
            case '3':
×
622
              if ((c = taosGetConsoleChar()) == '~') {
×
623
                // Delete key
624
                shellDeleteChar(&cmd);
×
625
              }
626
              break;
×
627
            case '4':
×
628
              if ((c = taosGetConsoleChar()) == '~') {
×
629
                // End key
630
                shellPositionCursorEnd(&cmd);
×
631
              }
632
              break;
×
633
            case '5':
×
634
              if ((c = taosGetConsoleChar()) == '~') {
×
635
                // Page up key
636
              }
637
              break;
×
638
            case '6':
×
639
              if ((c = taosGetConsoleChar()) == '~') {
×
640
                // Page down key
641
              }
642
              break;
×
643
            case 72:
×
644
              // Home key
645
              shellPositionCursorHome(&cmd);
×
646
              break;
×
647
            case 70:
×
648
              // End key
649
              shellPositionCursorEnd(&cmd);
×
650
              break;
×
651
          }
652
          break;
×
653
      }
654
    } else if (c == 0x7f) {
×
655
      pressOtherKey(c);
×
656
      // press delete key
657
      shellBackspaceChar(&cmd);
×
658
    } else {
659
      pressOtherKey(c);
×
660
      shellInsertChar(&cmd, &c, 1);
×
661
    }
662
  }
663

664
  return 0;
665
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc