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

taosdata / TDengine / #4961

09 Feb 2026 01:16AM UTC coverage: 66.798% (-0.08%) from 66.88%
#4961

push

travis-ci

web-flow
docs: add support for recording STMT to CSV files (#34276)

* docs: add support for recording STMT to CSV files

* docs: update version for STMT recording feature in CSV files

205534 of 307696 relevant lines covered (66.8%)

127069311.55 hits per line

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

29.2
/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 void    shellGetNextCharSize(const char *str, int32_t pos, int32_t *size, int32_t *width);
29

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

50
int32_t shellCountPrefixOnes(uint8_t c) {
×
51
  uint8_t mask = 0x80;
×
52
  int32_t count = 0;
×
53
  while ((c & mask) != 0) {
×
54
    count++;
×
55
    mask >>= 1;
×
56
  }
57

58
  return (count == 0) ? 1 : count;
×
59
}
60

61
void shellGetPrevCharSize(const char *str, int32_t pos, int32_t *size, int32_t *width) {
×
62
  if (pos <= 0) return;
×
63

64
  TdWchar wc;
×
65
  *size = 0;
×
66
  *width = 0;
×
67

68
  while (--pos >= 0) {
×
69
    *size += 1;
×
70
    if ((str[pos] & 0x80) == 0 || shellCountPrefixOnes((uint8_t)str[pos]) > 1) {
×
71
      break;
72
    }
73
  }
74

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

78
  *width = taosWcharWidth(wc);
×
79
}
80

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

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

89
void shellInsertChar(SShellCmd *cmd, char *c, int32_t size) {
4,488✔
90
  if(cmd->cursorOffset > cmd->commandSize || cmd->endOffset < cmd->screenOffset) return;
4,488✔
91

92
  TdWchar wc;
4,488✔
93
  if (taosMbToWchar(&wc, c, size) < 0) return;
4,488✔
94

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

106
  // set string end
107
  cmd->command[cmd->commandSize] = 0;
4,488✔
108
#ifdef WINDOWS
109
#else
110
  shellShowOnScreen(cmd);
4,488✔
111
#endif
112
}
113

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

294
bool shellIsReadyGo(SShellCmd *cmd) {
220✔
295
  if(cmd->cursorOffset > cmd->commandSize || cmd->endOffset < cmd->screenOffset) return false;
220✔
296

297
  char *total = (char *)taosMemoryCalloc(1, SHELL_MAX_COMMAND_SIZE);
220✔
298
  memset(cmd->command + cmd->commandSize, 0, SHELL_MAX_COMMAND_SIZE - cmd->commandSize);
220✔
299
  sprintf(total, "%s%s", cmd->buffer, cmd->command);
220✔
300

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

309
  taosMemoryFree(total);
×
310
  return false;
×
311
}
312

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

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

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

339

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

362
void shellClearScreen(int32_t ecmd_pos, int32_t cursor_pos) {
4,488✔
363
  int32_t ws_col;
4,488✔
364
  shellGetScreenSize(&ws_col, NULL);
4,488✔
365

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

383
void shellShowOnScreen(SShellCmd *cmd) {
4,928✔
384
  int32_t ws_col;
4,928✔
385
  shellGetScreenSize(&ws_col, NULL);
4,928✔
386

387
  TdWchar wc;
4,928✔
388
  int32_t size = 0;
4,928✔
389

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

418
    str = total_string + size;
77,616✔
419
  }
420

421
  taosMemoryFree(total_string);
4,928✔
422
  // Position the cursor
423
  int32_t cursor_pos = cmd->screenOffset + PSIZE;
4,928✔
424
  int32_t ecmd_pos = cmd->endOffset + PSIZE;
4,928✔
425

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

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

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

482
  cmd.buffer = (char *)taosMemoryCalloc(1, SHELL_MAX_COMMAND_SIZE);
440✔
483
  cmd.command = (char *)taosMemoryCalloc(1, SHELL_MAX_COMMAND_SIZE);
440✔
484
  shellShowOnScreen(&cmd);
440✔
485

486
  // Read input.
487
  char c;
440✔
488
  while (1) {
489
    c = taosGetConsoleChar();
4,928✔
490

491
    if (c == (char)EOF) {
4,928✔
492
      taosMemoryFreeClear(cmd.buffer);
220✔
493
      taosMemoryFreeClear(cmd.command);
220✔
494
      return c;
220✔
495
    }
496

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

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

662
  return 0;
663
}
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