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
-n, --no-autoconnect Disable automatic connect
-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)
-t, --timestamp Enable line timestamp
--timestamp-format <format> Set timestamp format (default: 24hour)

7
TODO
View file

@ -26,10 +26,11 @@
Time is in ms.
* Line mode feature
* Advanced line mode
Only send line when pressing enter. Maybe even add readline support so one
can use all the readline editing feature before sending the line.
Current line mode only support backspace editing. Would be nice with arrow
key navigation left/right and insert/overwrite support. Also history browsing
pressing up/down.
* 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
.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
\fBtwo-character hexadecimal\fR representation of the 1 byte value, e.g.: to
send \fI0xA\fR you must type \fI0a\fR or \fI0A\fR.
Set input mode.
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".

View file

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

View file

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

View file

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

View file

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

115
src/tty.c
View file

@ -195,8 +195,6 @@ static void optional_local_echo(char c)
{
log_putc(c);
}
print_tainted_set();
}
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");
break;
case INPUT_MODE_LINE:
option.input_mode = INPUT_MODE_LINE;
tio_printf("Switched to line input mode");
break;
case INPUT_MODE_END:
option.input_mode = INPUT_MODE_NORMAL;
tio_printf("Switched to normal input mode");
@ -1531,11 +1534,14 @@ int tty_connect(void)
fd_set rdfs; /* Read file descriptor set */
int maxfd; /* Maximum file descriptor used */
char input_char, output_char;
char input_buffer[BUFSIZ];
char input_buffer[BUFSIZ] = {};
char line_buffer[BUFSIZ] = {};
static bool first = true;
int status;
bool next_timestamp = false;
char* now = NULL;
unsigned int line_index = 0;
static char previous_char[2] = {};
/* Open tty device */
device_fd = open(option.tty_device, O_RDWR | O_NOCTTY | O_NONBLOCK);
@ -1805,12 +1811,107 @@ int tty_connect(void)
/* Handle commands */
handle_command_sequence(input_char, &output_char, &forward);
if ((option.input_mode == INPUT_MODE_HEX) && (forward))
if (forward)
{
if (!is_valid_hex(input_char))
switch (option.input_mode)
{
tio_warning_printf("Invalid hex character: '%d' (0x%02x)", input_char, input_char);
forward = false;
case INPUT_MODE_HEX:
if (!is_valid_hex(input_char))
{
tio_warning_printf("Invalid hex character: '%d' (0x%02x)", input_char, input_char);
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;
}
}
}