TDengine/tools/shell/src/shellCommand.c

609 lines
18 KiB
C
Raw Normal View History

2019-07-11 08:36:16 +00:00
/*
* 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
2022-04-20 11:13:22 +00:00
#include "shellInt.h"
2019-07-11 08:36:16 +00:00
2022-04-21 13:09:43 +00:00
#define LEFT 1
#define RIGHT 2
#define UP 3
#define DOWN 4
#define PSIZE shell.info.promptSize
2022-06-22 09:07:49 +00:00
#define SHELL_INPUT_MAX_COMMAND_SIZE 10000
2021-12-17 07:49:27 +00:00
2019-07-11 08:36:16 +00:00
typedef struct {
2022-04-21 13:09:43 +00:00
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;
2019-07-11 08:36:16 +00:00
mask = ~mask;
2022-04-21 13:09:43 +00:00
int32_t ret = 0;
2019-07-11 08:36:16 +00:00
while ((c & mask) != 0) {
ret++;
c <<= 1;
}
return ret;
}
2022-04-21 13:09:43 +00:00
void shellGetPrevCharSize(const char *str, int32_t pos, int32_t *size, int32_t *width) {
2019-07-11 08:36:16 +00:00
assert(pos > 0);
2022-03-18 08:48:12 +00:00
TdWchar wc;
2019-07-11 08:36:16 +00:00
*size = 0;
*width = 0;
while (--pos >= 0) {
*size += 1;
2022-04-21 13:09:43 +00:00
if (str[pos] > 0 || shellCountPrefixOnes((uint8_t)str[pos]) > 1) break;
2019-07-11 08:36:16 +00:00
}
2022-04-27 13:29:25 +00:00
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
2019-07-11 08:36:16 +00:00
2022-03-18 08:48:12 +00:00
*width = taosWcharWidth(wc);
2019-07-11 08:36:16 +00:00
}
2022-04-21 13:09:43 +00:00
void shellGetNextCharSize(const char *str, int32_t pos, int32_t *size, int32_t *width) {
2019-07-11 08:36:16 +00:00
assert(pos >= 0);
2022-03-18 08:48:12 +00:00
TdWchar wc;
*size = taosMbToWchar(&wc, str + pos, MB_CUR_MAX);
*width = taosWcharWidth(wc);
2019-07-11 08:36:16 +00:00
}
2022-04-21 13:09:43 +00:00
void shellInsertChar(SShellCmd *cmd, char *c, int32_t size) {
2019-07-11 08:36:16 +00:00
assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset);
2022-03-18 08:48:12 +00:00
TdWchar wc;
if (taosMbToWchar(&wc, c, size) < 0) return;
2019-07-11 08:36:16 +00:00
2022-04-21 13:09:43 +00:00
shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE);
2019-07-11 08:36:16 +00:00
/* 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;
2022-03-18 08:48:12 +00:00
cmd->screenOffset += taosWcharWidth(wc);
cmd->endOffset += taosWcharWidth(wc);
#ifdef WINDOWS
#else
2022-04-21 13:09:43 +00:00
shellShowOnScreen(cmd);
#endif
2019-07-11 08:36:16 +00:00
}
2022-04-21 13:09:43 +00:00
void shellBackspaceChar(SShellCmd *cmd) {
2019-07-11 08:36:16 +00:00
assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset);
if (cmd->cursorOffset > 0) {
2022-04-21 13:09:43 +00:00
shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE);
int32_t size = 0;
int32_t width = 0;
shellGetPrevCharSize(cmd->command, cmd->cursorOffset, &size, &width);
2019-07-11 08:36:16 +00:00
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;
2022-04-21 13:09:43 +00:00
shellShowOnScreen(cmd);
2019-07-11 08:36:16 +00:00
}
}
2022-04-21 13:09:43 +00:00
void shellClearLineBefore(SShellCmd *cmd) {
assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset);
2022-04-21 13:09:43 +00:00
shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE);
2022-04-18 13:14:32 +00:00
memmove(cmd->command, cmd->command + cmd->cursorOffset, cmd->commandSize - cmd->cursorOffset);
cmd->commandSize -= cmd->cursorOffset;
cmd->cursorOffset = 0;
cmd->screenOffset = 0;
cmd->endOffset = cmd->commandSize;
2022-04-21 13:09:43 +00:00
shellShowOnScreen(cmd);
}
2022-04-21 13:09:43 +00:00
void shellClearLineAfter(SShellCmd *cmd) {
assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset);
2022-04-21 13:09:43 +00:00
shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE);
cmd->commandSize -= cmd->endOffset - cmd->cursorOffset;
cmd->endOffset = cmd->cursorOffset;
2022-04-21 13:09:43 +00:00
shellShowOnScreen(cmd);
}
2022-04-21 13:09:43 +00:00
void shellDeleteChar(SShellCmd *cmd) {
2019-07-11 08:36:16 +00:00
assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset);
if (cmd->cursorOffset < cmd->commandSize) {
2022-04-21 13:09:43 +00:00
shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE);
int32_t size = 0;
int32_t width = 0;
shellGetNextCharSize(cmd->command, cmd->cursorOffset, &size, &width);
2019-07-11 08:36:16 +00:00
memmove(cmd->command + cmd->cursorOffset, cmd->command + cmd->cursorOffset + size,
cmd->commandSize - cmd->cursorOffset - size);
cmd->commandSize -= size;
cmd->endOffset -= width;
2022-04-21 13:09:43 +00:00
shellShowOnScreen(cmd);
2019-07-11 08:36:16 +00:00
}
}
2022-04-21 13:09:43 +00:00
void shellMoveCursorLeft(SShellCmd *cmd) {
2019-07-11 08:36:16 +00:00
assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset);
if (cmd->cursorOffset > 0) {
2022-04-21 13:09:43 +00:00
shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE);
int32_t size = 0;
int32_t width = 0;
shellGetPrevCharSize(cmd->command, cmd->cursorOffset, &size, &width);
2019-07-11 08:36:16 +00:00
cmd->cursorOffset -= size;
cmd->screenOffset -= width;
2022-04-21 13:09:43 +00:00
shellShowOnScreen(cmd);
2019-07-11 08:36:16 +00:00
}
}
2022-04-21 13:09:43 +00:00
void shellMoveCursorRight(SShellCmd *cmd) {
2019-07-11 08:36:16 +00:00
assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset);
if (cmd->cursorOffset < cmd->commandSize) {
2022-04-21 13:09:43 +00:00
shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE);
int32_t size = 0;
int32_t width = 0;
shellGetNextCharSize(cmd->command, cmd->cursorOffset, &size, &width);
2019-07-11 08:36:16 +00:00
cmd->cursorOffset += size;
cmd->screenOffset += width;
2022-04-21 13:09:43 +00:00
shellShowOnScreen(cmd);
2019-07-11 08:36:16 +00:00
}
}
2022-04-21 13:09:43 +00:00
void shellPositionCursorHome(SShellCmd *cmd) {
2019-07-11 08:36:16 +00:00
assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset);
if (cmd->cursorOffset > 0) {
2022-04-21 13:09:43 +00:00
shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE);
2019-07-11 08:36:16 +00:00
cmd->cursorOffset = 0;
cmd->screenOffset = 0;
2022-04-21 13:09:43 +00:00
shellShowOnScreen(cmd);
2019-07-11 08:36:16 +00:00
}
}
2022-04-21 13:09:43 +00:00
void shellPositionCursorEnd(SShellCmd *cmd) {
2019-07-11 08:36:16 +00:00
assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset);
if (cmd->cursorOffset < cmd->commandSize) {
2022-04-21 13:09:43 +00:00
shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE);
2019-07-11 08:36:16 +00:00
cmd->cursorOffset = cmd->commandSize;
cmd->screenOffset = cmd->endOffset;
2022-04-21 13:09:43 +00:00
shellShowOnScreen(cmd);
2019-07-11 08:36:16 +00:00
}
}
2022-04-21 13:09:43 +00:00
void shellPrintChar(char c, int32_t times) {
for (int32_t i = 0; i < times; i++) {
2019-07-11 08:36:16 +00:00
fprintf(stdout, "%c", c);
}
fflush(stdout);
}
2022-04-21 13:09:43 +00:00
void shellPositionCursor(int32_t step, int32_t direction) {
2022-06-22 09:07:49 +00:00
#ifndef WINDOWS
2019-07-11 08:36:16 +00:00
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);
}
2022-06-22 09:07:49 +00:00
#endif
2019-07-11 08:36:16 +00:00
}
2022-04-21 13:09:43 +00:00
void shellUpdateBuffer(SShellCmd *cmd) {
2019-07-11 08:36:16 +00:00
assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset);
2022-04-20 11:44:25 +00:00
if (shellRegexMatch(cmd->buffer, "(\\s+$)|(^$)", REG_EXTENDED)) strcat(cmd->command, " ");
2019-07-11 08:36:16 +00:00
strcat(cmd->buffer, cmd->command);
cmd->bufferSize += cmd->commandSize;
2022-04-21 13:09:43 +00:00
memset(cmd->command, 0, SHELL_MAX_COMMAND_SIZE);
2019-07-11 08:36:16 +00:00
cmd->cursorOffset = 0;
cmd->screenOffset = 0;
cmd->commandSize = 0;
cmd->endOffset = 0;
2022-04-21 13:09:43 +00:00
shellShowOnScreen(cmd);
2019-07-11 08:36:16 +00:00
}
2022-04-21 13:09:43 +00:00
int32_t shellIsReadyGo(SShellCmd *cmd) {
2019-07-11 08:36:16 +00:00
assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset);
2022-04-21 13:09:43 +00:00
char *total = (char *)taosMemoryCalloc(1, SHELL_MAX_COMMAND_SIZE);
memset(cmd->command + cmd->commandSize, 0, SHELL_MAX_COMMAND_SIZE - cmd->commandSize);
2019-07-11 08:36:16 +00:00
sprintf(total, "%s%s", cmd->buffer, cmd->command);
char *reg_str =
2022-04-18 13:14:32 +00:00
"(^.*;\\s*$)|(^\\s*$)|(^\\s*exit\\s*$)|(^\\s*q\\s*$)|(^\\s*quit\\s*$)|(^"
"\\s*clear\\s*$)";
2022-04-20 11:44:25 +00:00
if (shellRegexMatch(total, reg_str, REG_EXTENDED | REG_ICASE)) {
2022-03-25 16:29:53 +00:00
taosMemoryFree(total);
2019-07-11 08:36:16 +00:00
return 1;
}
2022-03-25 16:29:53 +00:00
taosMemoryFree(total);
2019-07-11 08:36:16 +00:00
return 0;
}
2022-04-21 13:09:43 +00:00
void shellGetMbSizeInfo(const char *str, int32_t *size, int32_t *width) {
TdWchar *wc = (TdWchar *)taosMemoryCalloc(sizeof(TdWchar), SHELL_MAX_COMMAND_SIZE);
2019-07-11 08:36:16 +00:00
*size = strlen(str);
2022-04-21 13:09:43 +00:00
taosMbsToWchars(wc, str, SHELL_MAX_COMMAND_SIZE);
*width = taosWcharsWidth(wc, SHELL_MAX_COMMAND_SIZE);
2022-03-25 16:29:53 +00:00
taosMemoryFree(wc);
2019-07-11 08:36:16 +00:00
}
2022-04-21 13:09:43 +00:00
void shellResetCommand(SShellCmd *cmd, const char s[]) {
2019-07-11 08:36:16 +00:00
assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset);
2022-04-21 13:09:43 +00:00
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);
2019-07-11 08:36:16 +00:00
cmd->bufferSize = 0;
cmd->commandSize = size;
cmd->cursorOffset = size;
cmd->screenOffset = width;
cmd->endOffset = width;
2022-04-21 13:09:43 +00:00
shellShowOnScreen(cmd);
2019-07-11 08:36:16 +00:00
}
2022-04-21 13:09:43 +00:00
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
2022-04-21 13:09:43 +00:00
struct winsize w;
if (ioctl(0, TIOCGWINSZ, &w) < 0 || w.ws_col == 0 || w.ws_row == 0) {
2022-07-06 06:38:24 +00:00
// fprintf(stderr, "No stream device, and use default value(col 120, row 30)\r\n");
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;
2022-04-21 13:09:43 +00:00
}
#endif
}
void shellClearScreen(int32_t ecmd_pos, int32_t cursor_pos) {
int32_t ws_col;
shellGetScreenSize(&ws_col, NULL);
2022-04-21 13:09:43 +00:00
int32_t cursor_x = cursor_pos / ws_col;
int32_t cursor_y = cursor_pos % ws_col;
int32_t command_x = ecmd_pos / ws_col;
2022-04-21 13:09:43 +00:00
shellPositionCursor(cursor_y, LEFT);
shellPositionCursor(command_x - cursor_x, DOWN);
2022-06-22 09:07:49 +00:00
#ifndef WINDOWS
2022-04-21 13:09:43 +00:00
fprintf(stdout, "\033[2K");
2022-06-22 09:07:49 +00:00
#endif
2022-04-21 13:09:43 +00:00
for (int32_t i = 0; i < command_x; i++) {
shellPositionCursor(1, UP);
2022-06-22 09:07:49 +00:00
#ifndef WINDOWS
2022-04-21 13:09:43 +00:00
fprintf(stdout, "\033[2K");
2022-06-22 09:07:49 +00:00
#endif
2022-04-21 13:09:43 +00:00
}
fflush(stdout);
2019-07-11 08:36:16 +00:00
}
2022-04-21 13:09:43 +00:00
void shellShowOnScreen(SShellCmd *cmd) {
int32_t ws_col;
shellGetScreenSize(&ws_col, NULL);
2022-04-21 13:09:43 +00:00
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);
}
int32_t remain_column = ws_col;
2022-04-21 13:09:43 +00:00
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);
remain_column = ws_col;
2022-04-21 13:09:43 +00:00
} else {
printf("\n\r%lc", wc);
remain_column = ws_col - width;
2022-04-21 13:09:43 +00:00
}
}
str = total_string + size;
}
taosMemoryFree(total_string);
// Position the cursor
int32_t cursor_pos = cmd->screenOffset + PSIZE;
int32_t ecmd_pos = cmd->endOffset + PSIZE;
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;
2022-04-21 13:09:43 +00:00
shellPositionCursor(command_y, LEFT);
shellPositionCursor(command_x, UP);
shellPositionCursor(cursor_x, DOWN);
shellPositionCursor(cursor_y, RIGHT);
fflush(stdout);
}
2022-06-22 09:07:49 +00:00
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;
2022-06-27 12:56:37 +00:00
while (bufLen == 0) {
2022-06-22 09:07:49 +00:00
ReadConsoleW(console, buf, SHELL_INPUT_MAX_COMMAND_SIZE, &bufLen, NULL);
2022-06-27 12:56:37 +00:00
if (bufLen > 0 && buf[0] == 0) bufLen = 0;
2022-06-22 09:07:49 +00:00
bufIndex = 0;
}
if (mbStrLen == 0){
2022-06-23 01:40:35 +00:00
if (buf[bufIndex] == '\r') {
bufIndex++;
}
2022-06-22 09:07:49 +00:00
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
}
2022-04-21 13:09:43 +00:00
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) {
2022-06-22 09:07:49 +00:00
c = taosGetConsoleChar();
2022-04-21 13:09:43 +00:00
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++) {
2022-06-22 09:07:49 +00:00
c = taosGetConsoleChar();
2022-04-21 13:09:43 +00:00
utf8_array[k] = c;
}
shellInsertChar(&cmd, utf8_array, count);
} else if (c < '\033') {
// Ctrl keys. TODO: Implement ctrl combinations
switch (c) {
2022-06-27 12:56:37 +00:00
case 0:
break;
2022-04-21 13:09:43 +00:00
case 1: // ctrl A
shellPositionCursorHome(&cmd);
break;
case 3:
2022-07-06 06:38:24 +00:00
printf("\r\n");
2022-04-21 13:09:43 +00:00
shellResetCommand(&cmd, "");
#ifdef WINDOWS
raise(SIGINT);
#else
kill(0, SIGINT);
#endif
2022-04-21 13:09:43 +00:00
break;
case 4: // EOF or Ctrl+D
2022-07-01 07:16:19 +00:00
taosResetTerminalMode();
2022-07-06 06:38:24 +00:00
printf("\r\n");
2022-04-21 13:09:43 +00:00
return -1;
case 5: // ctrl E
shellPositionCursorEnd(&cmd);
break;
case 8:
shellBackspaceChar(&cmd);
break;
case '\n':
case '\r':
#ifdef WINDOWS
#else
2022-07-06 06:38:24 +00:00
printf("\r\n");
#endif
2022-04-21 13:09:43 +00:00
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;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-result"
2022-04-21 13:09:43 +00:00
system("clear");
#pragma GCC diagnostic pop
2022-04-21 13:09:43 +00:00
shellShowOnScreen(&cmd);
break;
case 21: // Ctrl + U;
shellClearLineBefore(&cmd);
break;
}
} else if (c == '\033') {
2022-06-22 09:07:49 +00:00
c = taosGetConsoleChar();
2022-04-21 13:09:43 +00:00
switch (c) {
case '[':
2022-06-22 09:07:49 +00:00
c = taosGetConsoleChar();
2022-04-21 13:09:43 +00:00
switch (c) {
case 'A': // Up arrow
2022-07-23 06:07:20 +00:00
hist_counter = (hist_counter + SHELL_MAX_HISTORY_SIZE - 1) % SHELL_MAX_HISTORY_SIZE;
2022-08-02 12:03:45 +00:00
if (pHistory->hist[hist_counter] == NULL) {
hist_counter = (hist_counter + SHELL_MAX_HISTORY_SIZE + 1) % SHELL_MAX_HISTORY_SIZE;
} else {
shellResetCommand(&cmd, pHistory->hist[hist_counter]);
}
2022-04-21 13:09:43 +00:00
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':
2022-06-22 09:07:49 +00:00
if ((c = taosGetConsoleChar()) == '~') {
2022-04-21 13:09:43 +00:00
// Home key
shellPositionCursorHome(&cmd);
}
break;
case '2':
2022-06-22 09:07:49 +00:00
if ((c = taosGetConsoleChar()) == '~') {
2022-04-21 13:09:43 +00:00
// Insert key
}
break;
case '3':
2022-06-22 09:07:49 +00:00
if ((c = taosGetConsoleChar()) == '~') {
2022-04-21 13:09:43 +00:00
// Delete key
shellDeleteChar(&cmd);
}
break;
case '4':
2022-06-22 09:07:49 +00:00
if ((c = taosGetConsoleChar()) == '~') {
2022-04-21 13:09:43 +00:00
// End key
shellPositionCursorEnd(&cmd);
}
break;
case '5':
2022-06-22 09:07:49 +00:00
if ((c = taosGetConsoleChar()) == '~') {
2022-04-21 13:09:43 +00:00
// Page up key
}
break;
case '6':
2022-06-22 09:07:49 +00:00
if ((c = taosGetConsoleChar()) == '~') {
2022-04-21 13:09:43 +00:00
// 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;
}