Introduce basic line input mode

This commit is contained in:
Martin Lund 2024-04-16 17:42:34 +02:00
parent d60363a64c
commit 4801816357
8 changed files with 135 additions and 17 deletions

View file

@ -90,7 +90,7 @@ Options:
--line-pulse-duration <duration> Set line pulse duration --line-pulse-duration <duration> Set line pulse duration
-n, --no-autoconnect Disable automatic connect -n, --no-autoconnect Disable automatic connect
-e, --local-echo Enable local echo -e, --local-echo Enable local echo
--input-mode normal|hex Select input mode (default: normal) --input-mode normal|hex|line Select input mode (default: normal)
--output-mode normal|hex Select output mode (default: normal) --output-mode normal|hex Select output mode (default: normal)
-t, --timestamp Enable line timestamp -t, --timestamp Enable line timestamp
--timestamp-format <format> Set timestamp format (default: 24hour) --timestamp-format <format> Set timestamp format (default: 24hour)

7
TODO
View file

@ -26,10 +26,11 @@
Time is in ms. Time is in ms.
* Line mode feature * Advanced line mode
Only send line when pressing enter. Maybe even add readline support so one Current line mode only support backspace editing. Would be nice with arrow
can use all the readline editing feature before sending the line. key navigation left/right and insert/overwrite support. Also history browsing
pressing up/down.
* Support for interaction using simple autoresponse strings * Support for interaction using simple autoresponse strings

View file

@ -191,11 +191,18 @@ If defining more than one flag, the flags must be comma separated.
.RE .RE
.TP .TP
.BR " \-\-input\-mode " normal|hex .BR " \-\-input\-mode " normal|hex|line
Set input mode. In hex input mode bytes can be sent by typing the Set input mode.
\fBtwo-character hexadecimal\fR representation of the 1 byte value, e.g.: to
send \fI0xA\fR you must type \fI0a\fR or \fI0A\fR. In normal mode input characters are sent immediately as they are typed.
In hex input mode bytes can be sent by typing the \fBtwo-character
hexadecimal\fR representation of the 1 byte value, e.g.: to send \fI0xA\fR you
must type \fI0a\fR or \fI0A\fR.
In line input mode input characters are sent when you press enter. The only
editing feature supported in this mode is backspace.
Default value is "normal". Default value is "normal".

View file

@ -131,7 +131,7 @@ _tio()
return 0 return 0
;; ;;
--input-mode) --input-mode)
COMPREPLY=( $(compgen -W "normal hex" -- ${cur}) ) COMPREPLY=( $(compgen -W "normal hex line" -- ${cur}) )
return 0 return 0
;; ;;
--output-mode) --output-mode)

View file

@ -126,7 +126,7 @@ void print_help(char *argv[])
printf(" --line-pulse-duration <duration> Set line pulse duration\n"); printf(" --line-pulse-duration <duration> Set line pulse duration\n");
printf(" -n, --no-autoconnect Disable automatic connect\n"); printf(" -n, --no-autoconnect Disable automatic connect\n");
printf(" -e, --local-echo Enable local echo\n"); printf(" -e, --local-echo Enable local echo\n");
printf(" --input-mode normal|hex Select input mode (default: normal)\n"); printf(" --input-mode normal|hex|line Select input mode (default: normal)\n");
printf(" --output-mode normal|hex Select output mode (default: normal)\n"); printf(" --output-mode normal|hex Select output mode (default: normal)\n");
printf(" -t, --timestamp Enable line timestamp\n"); printf(" -t, --timestamp Enable line timestamp\n");
printf(" --timestamp-format <format> Set timestamp format (default: 24hour)\n"); printf(" --timestamp-format <format> Set timestamp format (default: 24hour)\n");
@ -226,6 +226,10 @@ input_mode_t input_mode_option_parse(const char *arg)
{ {
return INPUT_MODE_HEX; return INPUT_MODE_HEX;
} }
else if (strcmp("line", arg) == 0)
{
return INPUT_MODE_LINE;
}
else else
{ {
tio_error_printf("Invalid input mode option"); tio_error_printf("Invalid input mode option");
@ -258,6 +262,8 @@ const char *input_mode_by_string(input_mode_t mode)
return "normal"; return "normal";
case INPUT_MODE_HEX: case INPUT_MODE_HEX:
return "hex"; return "hex";
case INPUT_MODE_LINE:
return "line";
case INPUT_MODE_END: case INPUT_MODE_END:
break; break;
} }

View file

@ -34,6 +34,7 @@ typedef enum
{ {
INPUT_MODE_NORMAL, INPUT_MODE_NORMAL,
INPUT_MODE_HEX, INPUT_MODE_HEX,
INPUT_MODE_LINE,
INPUT_MODE_END, INPUT_MODE_END,
} input_mode_t; } input_mode_t;

View file

@ -31,11 +31,13 @@ char ansi_format[30];
void print_hex(char c) void print_hex(char c)
{ {
print_tainted = true;
printf("%02x ", (unsigned char) c); printf("%02x ", (unsigned char) c);
} }
void print_normal(char c) void print_normal(char c)
{ {
print_tainted = true;
putchar(c); putchar(c);
} }

109
src/tty.c
View file

@ -195,8 +195,6 @@ static void optional_local_echo(char c)
{ {
log_putc(c); log_putc(c);
} }
print_tainted_set();
} }
inline static bool is_valid_hex(char c) inline static bool is_valid_hex(char c)
@ -887,6 +885,11 @@ void handle_command_sequence(char input_char, char *output_char, bool *forward)
tio_printf("Switched to hex input mode"); tio_printf("Switched to hex input mode");
break; break;
case INPUT_MODE_LINE:
option.input_mode = INPUT_MODE_LINE;
tio_printf("Switched to line input mode");
break;
case INPUT_MODE_END: case INPUT_MODE_END:
option.input_mode = INPUT_MODE_NORMAL; option.input_mode = INPUT_MODE_NORMAL;
tio_printf("Switched to normal input mode"); tio_printf("Switched to normal input mode");
@ -1531,11 +1534,14 @@ int tty_connect(void)
fd_set rdfs; /* Read file descriptor set */ fd_set rdfs; /* Read file descriptor set */
int maxfd; /* Maximum file descriptor used */ int maxfd; /* Maximum file descriptor used */
char input_char, output_char; char input_char, output_char;
char input_buffer[BUFSIZ]; char input_buffer[BUFSIZ] = {};
char line_buffer[BUFSIZ] = {};
static bool first = true; static bool first = true;
int status; int status;
bool next_timestamp = false; bool next_timestamp = false;
char* now = NULL; char* now = NULL;
unsigned int line_index = 0;
static char previous_char[2] = {};
/* Open tty device */ /* Open tty device */
device_fd = open(option.tty_device, O_RDWR | O_NOCTTY | O_NONBLOCK); device_fd = open(option.tty_device, O_RDWR | O_NOCTTY | O_NONBLOCK);
@ -1805,13 +1811,108 @@ int tty_connect(void)
/* Handle commands */ /* Handle commands */
handle_command_sequence(input_char, &output_char, &forward); handle_command_sequence(input_char, &output_char, &forward);
if ((option.input_mode == INPUT_MODE_HEX) && (forward)) if (forward)
{ {
switch (option.input_mode)
{
case INPUT_MODE_HEX:
if (!is_valid_hex(input_char)) if (!is_valid_hex(input_char))
{ {
tio_warning_printf("Invalid hex character: '%d' (0x%02x)", input_char, input_char); tio_warning_printf("Invalid hex character: '%d' (0x%02x)", input_char, input_char);
forward = false; forward = false;
} }
break;
case INPUT_MODE_LINE:
switch (input_char)
{
case 27: // Escape
forward = false;
break;
case '[':
if (previous_char[0] == 27)
{
forward = false;
}
break;
case 'A':
case 'B':
case 'C':
case 'D':
if ((previous_char[1] == 27) && (previous_char[0] == '['))
{
// Handle arrow keys
switch (input_char)
{
case 'A': // Up arrow
// Ignore
break;
case 'B': // Down arrow
// Ignore
break;
case 'C': // Right arrow
// Ignore
break;
case 'D': // Left arrow
// Ignore
break;
}
forward = false;
}
break;
case '\b':
case 127: // Backspace
if (line_index)
{
if ((option.output_mode == OUTPUT_MODE_HEX) && (option.local_echo))
{
printf("\b\b\b \b\b\b"); // Destructive backspace
}
else
{
printf("\b \b"); // Destructive backspace
}
line_index--;
}
forward = false;
break;
case 13: // Carriage return
// Write buffered line to tty device
tty_write(device_fd, line_buffer, line_index);
tty_write(device_fd, "\r", 1);
optional_local_echo('\r');
tty_sync(device_fd);
putchar('\r');
putchar('\n');
line_index = 0;
forward = false;
break;
default:
if (line_index < BUFSIZ)
{
line_buffer[line_index++] = input_char;
}
else
{
tio_error_print("Input exceeds maximum line length. Truncating.");
forward = false;
}
}
// Save 2 latest stdin input characters
previous_char[1] = previous_char[0];
previous_char[0] = input_char;
break;
default:
break;
}
} }
} }