diff --git a/src/bash-completion/tio.in b/src/bash-completion/tio.in index 7e110f6..82cb649 100644 --- a/src/bash-completion/tio.in +++ b/src/bash-completion/tio.in @@ -159,12 +159,14 @@ _tio() ;; esac + sub_configs="`tio --complete-sub-configs`" + if [ -d /dev/serial/by-id ]; then ttys=$(printf '%s\n' /dev/tty* /dev/serial/by-id/*) else ttys=$(printf '%s\n' /dev/tty*) fi - COMPREPLY=( $(compgen -W "${ttys}" -- ${cur}) ) + COMPREPLY=( $(compgen -W "${ttys} ${sub_configs}" -- ${cur}) ) return 0 } diff --git a/src/configfile.c b/src/configfile.c index 864380e..b9ebf2f 100644 --- a/src/configfile.c +++ b/src/configfile.c @@ -342,6 +342,24 @@ static int section_name_search_handler(void *user, const char *section, const ch return 0; } +static int section_name_print_handler(void *user, const char *section, const char *varname, + const char *varval) +{ + UNUSED(user); + UNUSED(varname); + UNUSED(varval); + + static char *section_previous = ""; + + if (strcmp(section, section_previous) != 0) + { + printf("%s ", section); + section_previous = strdup(section); + } + + return 0; +} + static int resolve_config_file(void) { asprintf(&c->path, "%s/tio/tiorc", getenv("XDG_CONFIG_HOME")); @@ -373,6 +391,26 @@ static int resolve_config_file(void) return -EINVAL; } +void config_file_show_sub_configurations(void) +{ + c = malloc(sizeof(struct config_t)); + if (!c) + { + tio_error_printf("Insufficient memory allocation"); + exit(EXIT_FAILURE); + } + memset(c, 0, sizeof(struct config_t)); + + // Find config file + if (resolve_config_file() != 0) + { + // None found - stop parsing + return; + } + + ini_parse(c->path, section_name_print_handler, NULL); +} + void config_file_parse(void) { int ret; @@ -382,7 +420,7 @@ void config_file_parse(void) { tio_error_printf("Insufficient memory allocation"); exit(EXIT_FAILURE); - } + } memset(c, 0, sizeof(struct config_t)); // Find config file diff --git a/src/configfile.h b/src/configfile.h index 6d0cc30..1f6f8b7 100644 --- a/src/configfile.h +++ b/src/configfile.h @@ -41,3 +41,4 @@ struct config_t void config_file_print(void); void config_file_parse(void); void config_exit(void); +void config_file_show_sub_configurations(void); diff --git a/src/main.c b/src/main.c index 02f8a47..d2b1c0d 100644 --- a/src/main.c +++ b/src/main.c @@ -45,6 +45,12 @@ int main(int argc, char *argv[]) /* Parse command-line options (1st pass) */ options_parse(argc, argv); + if (option.complete_sub_configs) + { + config_file_show_sub_configurations(); + return status; + } + /* Parse configuration file */ config_file_parse(); diff --git a/src/options.c b/src/options.c index d21ed87..35608f7 100644 --- a/src/options.c +++ b/src/options.c @@ -50,6 +50,7 @@ enum opt_t OPT_RS485, OPT_RS485_CONFIG, OPT_ALERT, + OPT_COMPLETE_SUB_CONFIGS, }; /* Default options */ @@ -89,6 +90,7 @@ struct option_t option = .rs485_delay_rts_before_send = -1, .rs485_delay_rts_after_send = -1, .alert = ALERT_NONE, + .complete_sub_configs = false, }; void print_help(char *argv[]) @@ -229,34 +231,35 @@ void options_parse(int argc, char *argv[]) { static struct option long_options[] = { - {"baudrate", required_argument, 0, 'b' }, - {"databits", required_argument, 0, 'd' }, - {"flow", required_argument, 0, 'f' }, - {"stopbits", required_argument, 0, 's' }, - {"parity", required_argument, 0, 'p' }, - {"output-delay", required_argument, 0, 'o' }, - {"output-line-delay" , required_argument, 0, 'O' }, - {"line-pulse-duration", required_argument, 0, OPT_LINE_PULSE_DURATION}, - {"no-autoconnect", no_argument, 0, 'n' }, - {"local-echo", no_argument, 0, 'e' }, - {"timestamp", no_argument, 0, 't' }, - {"timestamp-format", required_argument, 0, OPT_TIMESTAMP_FORMAT }, - {"list-devices", no_argument, 0, 'L' }, - {"log", no_argument, 0, 'l' }, - {"log-file", required_argument, 0, OPT_LOG_FILE }, - {"log-strip", no_argument, 0, OPT_LOG_STRIP }, - {"socket", required_argument, 0, 'S' }, - {"map", required_argument, 0, 'm' }, - {"color", required_argument, 0, 'c' }, - {"hexadecimal", no_argument, 0, 'x' }, - {"response-wait", no_argument, 0, 'r' }, - {"response-timeout", required_argument, 0, OPT_RESPONSE_TIMEOUT }, - {"rs-485", no_argument, 0, OPT_RS485 }, - {"rs-485-config", required_argument, 0, OPT_RS485_CONFIG }, - {"alert", required_argument, 0, OPT_ALERT }, - {"version", no_argument, 0, 'v' }, - {"help", no_argument, 0, 'h' }, - {0, 0, 0, 0 } + {"baudrate", required_argument, 0, 'b' }, + {"databits", required_argument, 0, 'd' }, + {"flow", required_argument, 0, 'f' }, + {"stopbits", required_argument, 0, 's' }, + {"parity", required_argument, 0, 'p' }, + {"output-delay", required_argument, 0, 'o' }, + {"output-line-delay" , required_argument, 0, 'O' }, + {"line-pulse-duration", required_argument, 0, OPT_LINE_PULSE_DURATION }, + {"no-autoconnect", no_argument, 0, 'n' }, + {"local-echo", no_argument, 0, 'e' }, + {"timestamp", no_argument, 0, 't' }, + {"timestamp-format", required_argument, 0, OPT_TIMESTAMP_FORMAT }, + {"list-devices", no_argument, 0, 'L' }, + {"log", no_argument, 0, 'l' }, + {"log-file", required_argument, 0, OPT_LOG_FILE }, + {"log-strip", no_argument, 0, OPT_LOG_STRIP }, + {"socket", required_argument, 0, 'S' }, + {"map", required_argument, 0, 'm' }, + {"color", required_argument, 0, 'c' }, + {"hexadecimal", no_argument, 0, 'x' }, + {"response-wait", no_argument, 0, 'r' }, + {"response-timeout", required_argument, 0, OPT_RESPONSE_TIMEOUT }, + {"rs-485", no_argument, 0, OPT_RS485 }, + {"rs-485-config", required_argument, 0, OPT_RS485_CONFIG }, + {"alert", required_argument, 0, OPT_ALERT }, + {"version", no_argument, 0, 'v' }, + {"help", no_argument, 0, 'h' }, + {"complete-sub-configs", no_argument, 0, OPT_COMPLETE_SUB_CONFIGS}, + {0, 0, 0, 0 } }; /* getopt_long stores the option index here */ @@ -418,6 +421,10 @@ void options_parse(int argc, char *argv[]) exit(EXIT_SUCCESS); break; + case OPT_COMPLETE_SUB_CONFIGS: + option.complete_sub_configs = true; + break; + case '?': /* getopt_long already printed an error message */ exit(EXIT_FAILURE); @@ -434,6 +441,11 @@ void options_parse(int argc, char *argv[]) else if (optind < argc) option.tty_device = argv[optind++]; + if (option.complete_sub_configs) + { + return; + } + if (strlen(option.tty_device) == 0) { tio_error_printf("Missing tty device or sub-configuration name"); diff --git a/src/options.h b/src/options.h index 22ec236..8ae556d 100644 --- a/src/options.h +++ b/src/options.h @@ -66,6 +66,7 @@ struct option_t int32_t rs485_delay_rts_before_send; int32_t rs485_delay_rts_after_send; enum alert_t alert; + bool complete_sub_configs; }; extern struct option_t option;