Skip to content

Commit

Permalink
Revert "[FL-3909] CLI improvements, part I (flipperdevices#3928)" (fl…
Browse files Browse the repository at this point in the history
…ipperdevices#3955)

This reverts commit 0f83141.

Co-authored-by: あく <[email protected]>
  • Loading branch information
portasynthinca3 and skotopes authored Oct 17, 2024
1 parent ca68c95 commit b723d46
Show file tree
Hide file tree
Showing 9 changed files with 101 additions and 528 deletions.
9 changes: 5 additions & 4 deletions applications/main/subghz/subghz_cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -999,12 +999,13 @@ static void subghz_cli_command_chat(Cli* cli, FuriString* args) {
chat_event = subghz_chat_worker_get_event_chat(subghz_chat);
switch(chat_event.event) {
case SubGhzChatEventInputData:
if(chat_event.c == CliKeyETX) {
if(chat_event.c == CliSymbolAsciiETX) {
printf("\r\n");
chat_event.event = SubGhzChatEventUserExit;
subghz_chat_worker_put_event_chat(subghz_chat, &chat_event);
break;
} else if((chat_event.c == CliKeyBackspace) || (chat_event.c == CliKeyDEL)) {
} else if(
(chat_event.c == CliSymbolAsciiBackspace) || (chat_event.c == CliSymbolAsciiDel)) {
size_t len = furi_string_utf8_length(input);
if(len > furi_string_utf8_length(name)) {
printf("%s", "\e[D\e[1P");
Expand All @@ -1026,7 +1027,7 @@ static void subghz_cli_command_chat(Cli* cli, FuriString* args) {
}
furi_string_set(input, sysmsg);
}
} else if(chat_event.c == CliKeyCR) {
} else if(chat_event.c == CliSymbolAsciiCR) {
printf("\r\n");
furi_string_push_back(input, '\r');
furi_string_push_back(input, '\n');
Expand All @@ -1040,7 +1041,7 @@ static void subghz_cli_command_chat(Cli* cli, FuriString* args) {
furi_string_printf(input, "%s", furi_string_get_cstr(name));
printf("%s", furi_string_get_cstr(input));
fflush(stdout);
} else if(chat_event.c == CliKeyLF) {
} else if(chat_event.c == CliSymbolAsciiLF) {
//cut out the symbol \n
} else {
putc(chat_event.c, stdout);
Expand Down
1 change: 0 additions & 1 deletion applications/main/subghz/subghz_cli.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#pragma once

#include <cli/cli.h>
#include <cli/cli_ansi.h>

void subghz_on_system_start(void);
194 changes: 48 additions & 146 deletions applications/services/cli/cli.c
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
#include "cli_i.h"
#include "cli_commands.h"
#include "cli_vcp.h"
#include "cli_ansi.h"
#include <furi_hal_version.h>
#include <loader/loader.h>

#define TAG "CliSrv"

#define CLI_INPUT_LEN_LIMIT 256
#define CLI_PROMPT ">: " // qFlipper does not recognize us if we use escape sequences :(
#define CLI_PROMPT_LENGTH 3 // printable characters

Cli* cli_alloc(void) {
Cli* cli = malloc(sizeof(Cli));
Expand Down Expand Up @@ -88,7 +85,7 @@ bool cli_cmd_interrupt_received(Cli* cli) {
char c = '\0';
if(cli_is_connected(cli)) {
if(cli->session->rx((uint8_t*)&c, 1, 0) == 1) {
return c == CliKeyETX;
return c == CliSymbolAsciiETX;
}
} else {
return true;
Expand All @@ -105,8 +102,7 @@ void cli_print_usage(const char* cmd, const char* usage, const char* arg) {
}

void cli_motd(void) {
printf(ANSI_FLIPPER_BRAND_ORANGE
"\r\n"
printf("\r\n"
" _.-------.._ -,\r\n"
" .-\"```\"--..,,_/ /`-, -, \\ \r\n"
" .:\" /:/ /'\\ \\ ,_..., `. | |\r\n"
Expand All @@ -120,11 +116,12 @@ void cli_motd(void) {
" _L_ _ ___ ___ ___ ___ ____--\"`___ _ ___\r\n"
"| __|| | |_ _|| _ \\| _ \\| __|| _ \\ / __|| | |_ _|\r\n"
"| _| | |__ | | | _/| _/| _| | / | (__ | |__ | |\r\n"
"|_| |____||___||_| |_| |___||_|_\\ \\___||____||___|\r\n" ANSI_RESET
"\r\n" ANSI_FG_BR_WHITE "Welcome to " ANSI_FLIPPER_BRAND_ORANGE
"Flipper Zero" ANSI_FG_BR_WHITE " Command Line Interface!\r\n"
"|_| |____||___||_| |_| |___||_|_\\ \\___||____||___|\r\n"
"\r\n"
"Welcome to Flipper Zero Command Line Interface!\r\n"
"Read the manual: https://docs.flipper.net/development/cli\r\n"
"Run `help` or `?` to list available commands\r\n" ANSI_RESET "\r\n");
"Run `help` or `?` to list available commands\r\n"
"\r\n");

const Version* firmware_version = furi_hal_version_get_firmware_version();
if(firmware_version) {
Expand All @@ -145,7 +142,7 @@ void cli_nl(Cli* cli) {

void cli_prompt(Cli* cli) {
UNUSED(cli);
printf("\r\n" CLI_PROMPT "%s", furi_string_get_cstr(cli->line));
printf("\r\n>: %s", furi_string_get_cstr(cli->line));
fflush(stdout);
}

Expand All @@ -168,7 +165,7 @@ static void cli_handle_backspace(Cli* cli) {

cli->cursor_position--;
} else {
cli_putc(cli, CliKeyBell);
cli_putc(cli, CliSymbolAsciiBell);
}
}

Expand Down Expand Up @@ -244,7 +241,7 @@ static void cli_handle_enter(Cli* cli) {
printf(
"`%s` command not found, use `help` or `?` to list all available commands",
furi_string_get_cstr(command));
cli_putc(cli, CliKeyBell);
cli_putc(cli, CliSymbolAsciiBell);
}

cli_reset(cli);
Expand Down Expand Up @@ -308,85 +305,8 @@ static void cli_handle_autocomplete(Cli* cli) {
cli_prompt(cli);
}

typedef enum {
CliCharClassWord,
CliCharClassSpace,
CliCharClassOther,
} CliCharClass;

/**
* @brief Determines the class that a character belongs to
*
* The return value of this function should not be used on its own; it should
* only be used for comparing it with other values returned by this function.
* This function is used internally in `cli_skip_run`.
*/
static CliCharClass cli_char_class(char c) {
if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '_') {
return CliCharClassWord;
} else if(c == ' ') {
return CliCharClassSpace;
} else {
return CliCharClassOther;
}
}

typedef enum {
CliSkipDirectionLeft,
CliSkipDirectionRight,
} CliSkipDirection;

/**
* @brief Skips a run of a class of characters
*
* @param string Input string
* @param original_pos Position to start the search at
* @param direction Direction in which to perform the search
* @returns The position at which the run ends
*/
static size_t cli_skip_run(FuriString* string, size_t original_pos, CliSkipDirection direction) {
if(furi_string_size(string) == 0) return original_pos;
if(direction == CliSkipDirectionLeft && original_pos == 0) return original_pos;
if(direction == CliSkipDirectionRight && original_pos == furi_string_size(string))
return original_pos;

int8_t look_offset = (direction == CliSkipDirectionLeft) ? -1 : 0;
int8_t increment = (direction == CliSkipDirectionLeft) ? -1 : 1;
int32_t position = original_pos;
CliCharClass start_class =
cli_char_class(furi_string_get_char(string, position + look_offset));

while(true) {
position += increment;
if(position < 0) break;
if(position >= (int32_t)furi_string_size(string)) break;
if(cli_char_class(furi_string_get_char(string, position + look_offset)) != start_class)
break;
}

return MAX(0, position);
}

void cli_process_input(Cli* cli) {
CliKeyCombo combo = cli_read_ansi_key_combo(cli);
FURI_LOG_T(TAG, "code=0x%02x, mod=0x%x\r\n", combo.key, combo.modifiers);

if(combo.key == CliKeyTab) {
cli_handle_autocomplete(cli);

} else if(combo.key == CliKeySOH) {
furi_delay_ms(33); // We are too fast, Minicom is not ready yet
cli_motd();
cli_prompt(cli);

} else if(combo.key == CliKeyETX) {
cli_reset(cli);
cli_prompt(cli);

} else if(combo.key == CliKeyEOT) {
cli_reset(cli);

} else if(combo.key == CliKeyUp && combo.modifiers == CliModKeyNo) {
static void cli_handle_escape(Cli* cli, char c) {
if(c == 'A') {
// Use previous command if line buffer is empty
if(furi_string_size(cli->line) == 0 && furi_string_cmp(cli->line, cli->last_line) != 0) {
// Set line buffer and cursor position
Expand All @@ -395,85 +315,67 @@ void cli_process_input(Cli* cli) {
// Show new line to user
printf("%s", furi_string_get_cstr(cli->line));
}

} else if(combo.key == CliKeyDown && combo.modifiers == CliModKeyNo) {
// Clear input buffer
furi_string_reset(cli->line);
cli->cursor_position = 0;
printf("\r" CLI_PROMPT "\e[0K");

} else if(combo.key == CliKeyRight && combo.modifiers == CliModKeyNo) {
// Move right
} else if(c == 'B') {
} else if(c == 'C') {
if(cli->cursor_position < furi_string_size(cli->line)) {
cli->cursor_position++;
printf("\e[C");
}

} else if(combo.key == CliKeyLeft && combo.modifiers == CliModKeyNo) {
// Move left
} else if(c == 'D') {
if(cli->cursor_position > 0) {
cli->cursor_position--;
printf("\e[D");
}
}
fflush(stdout);
}

} else if(combo.key == CliKeyHome && combo.modifiers == CliModKeyNo) {
// Move to beginning of line
cli->cursor_position = 0;
printf("\e[%uG", CLI_PROMPT_LENGTH + 1); // columns start at 1 \(-_-)/

} else if(combo.key == CliKeyEnd && combo.modifiers == CliModKeyNo) {
// Move to end of line
cli->cursor_position = furi_string_size(cli->line);
printf("\e[%zuG", CLI_PROMPT_LENGTH + cli->cursor_position + 1);
void cli_process_input(Cli* cli) {
char in_chr = cli_getc(cli);
size_t rx_len;

} else if(
combo.modifiers == CliModKeyCtrl &&
(combo.key == CliKeyLeft || combo.key == CliKeyRight)) {
// Skip run of similar chars to the left or right
CliSkipDirection direction = (combo.key == CliKeyLeft) ? CliSkipDirectionLeft :
CliSkipDirectionRight;
cli->cursor_position = cli_skip_run(cli->line, cli->cursor_position, direction);
printf("\e[%zuG", CLI_PROMPT_LENGTH + cli->cursor_position + 1);

} else if(combo.key == CliKeyBackspace || combo.key == CliKeyDEL) {
if(in_chr == CliSymbolAsciiTab) {
cli_handle_autocomplete(cli);
} else if(in_chr == CliSymbolAsciiSOH) {
furi_delay_ms(33); // We are too fast, Minicom is not ready yet
cli_motd();
cli_prompt(cli);
} else if(in_chr == CliSymbolAsciiETX) {
cli_reset(cli);
cli_prompt(cli);
} else if(in_chr == CliSymbolAsciiEOT) {
cli_reset(cli);
} else if(in_chr == CliSymbolAsciiEsc) {
rx_len = cli_read(cli, (uint8_t*)&in_chr, 1);
if((rx_len > 0) && (in_chr == '[')) {
cli_read(cli, (uint8_t*)&in_chr, 1);
cli_handle_escape(cli, in_chr);
} else {
cli_putc(cli, CliSymbolAsciiBell);
}
} else if(in_chr == CliSymbolAsciiBackspace || in_chr == CliSymbolAsciiDel) {
cli_handle_backspace(cli);

} else if(combo.key == CliKeyETB) { // Ctrl + Backspace
// Delete run of similar chars to the left
size_t run_start = cli_skip_run(cli->line, cli->cursor_position, CliSkipDirectionLeft);
furi_string_replace_at(cli->line, run_start, cli->cursor_position - run_start, "");
cli->cursor_position = run_start;
printf(
"\e[%zuG%s\e[0K\e[%zuG", // move cursor, print second half of line, erase remains, move cursor again
CLI_PROMPT_LENGTH + cli->cursor_position + 1,
furi_string_get_cstr(cli->line) + run_start,
CLI_PROMPT_LENGTH + run_start + 1);

} else if(combo.key == CliKeyCR) {
} else if(in_chr == CliSymbolAsciiCR) {
cli_handle_enter(cli);

} else if(
(combo.key >= 0x20 && combo.key < 0x7F) && //-V560
(in_chr >= 0x20 && in_chr < 0x7F) && //-V560
(furi_string_size(cli->line) < CLI_INPUT_LEN_LIMIT)) {
if(cli->cursor_position == furi_string_size(cli->line)) {
furi_string_push_back(cli->line, combo.key);
cli_putc(cli, combo.key);
furi_string_push_back(cli->line, in_chr);
cli_putc(cli, in_chr);
} else {
// Insert character to line buffer
const char in_str[2] = {combo.key, 0};
const char in_str[2] = {in_chr, 0};
furi_string_replace_at(cli->line, cli->cursor_position, 0, in_str);

// Print character in replace mode
printf("\e[4h%c\e[4l", combo.key);
printf("\e[4h%c\e[4l", in_chr);
fflush(stdout);
}
cli->cursor_position++;

} else {
cli_putc(cli, CliKeyBell);
cli_putc(cli, CliSymbolAsciiBell);
}

fflush(stdout);
}

void cli_add_command(
Expand Down
16 changes: 15 additions & 1 deletion applications/services/cli/cli.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,26 @@
extern "C" {
#endif

typedef enum {
CliSymbolAsciiSOH = 0x01,
CliSymbolAsciiETX = 0x03,
CliSymbolAsciiEOT = 0x04,
CliSymbolAsciiBell = 0x07,
CliSymbolAsciiBackspace = 0x08,
CliSymbolAsciiTab = 0x09,
CliSymbolAsciiLF = 0x0A,
CliSymbolAsciiCR = 0x0D,
CliSymbolAsciiEsc = 0x1B,
CliSymbolAsciiUS = 0x1F,
CliSymbolAsciiSpace = 0x20,
CliSymbolAsciiDel = 0x7F,
} CliSymbols;

typedef enum {
CliCommandFlagDefault = 0, /**< Default, loader lock is used */
CliCommandFlagParallelSafe =
(1 << 0), /**< Safe to run in parallel with other apps, loader lock is not used */
CliCommandFlagInsomniaSafe = (1 << 1), /**< Safe to run with insomnia mode on */
CliCommandFlagHidden = (1 << 2), /**< Not shown in `help` */
} CliCommandFlag;

#define RECORD_CLI "cli"
Expand Down
Loading

0 comments on commit b723d46

Please sign in to comment.