diff --git a/configure.ac b/configure.ac index fdece2791..09332567f 100644 --- a/configure.ac +++ b/configure.ac @@ -644,6 +644,7 @@ tests/lib/Makefile tests/lib/mcconfig/Makefile tests/lib/search/Makefile tests/lib/vfs/Makefile +tests/lib/widget/Makefile tests/src/Makefile tests/src/filemanager/Makefile ]) diff --git a/lib/vfs/utilvfs.c b/lib/vfs/utilvfs.c index bdc212473..d16ff0681 100644 --- a/lib/vfs/utilvfs.c +++ b/lib/vfs/utilvfs.c @@ -349,7 +349,8 @@ vfs_die (const char *m) char * vfs_get_password (const char *msg) { - return input_dialog (msg, _("Password:"), MC_HISTORY_VFS_PASSWORD, INPUT_PASSWORD); + return input_dialog (msg, _("Password:"), MC_HISTORY_VFS_PASSWORD, INPUT_PASSWORD, + INPUT_COMPLETE_NONE); } /* --------------------------------------------------------------------------------------------- */ diff --git a/lib/widget/input.h b/lib/widget/input.h index ff6a50554..eb0d1b88f 100644 --- a/lib/widget/input.h +++ b/lib/widget/input.h @@ -29,6 +29,7 @@ typedef enum /* completion flags */ typedef enum { + INPUT_COMPLETE_NONE = 0, INPUT_COMPLETE_FILENAMES = 1 << 0, INPUT_COMPLETE_HOSTNAMES = 1 << 1, INPUT_COMPLETE_COMMANDS = 1 << 2, @@ -36,9 +37,6 @@ typedef enum INPUT_COMPLETE_USERNAMES = 1 << 4, INPUT_COMPLETE_CD = 1 << 5, INPUT_COMPLETE_SHELL_ESC = 1 << 6, - - INPUT_COMPLETE_DEFAULT = INPUT_COMPLETE_FILENAMES - | INPUT_COMPLETE_HOSTNAMES | INPUT_COMPLETE_VARIABLES | INPUT_COMPLETE_USERNAMES } input_complete_t; /*** structures declarations (and typedefs of structures)*****************************************/ diff --git a/lib/widget/input_complete.c b/lib/widget/input_complete.c index b47a506a4..98791b948 100644 --- a/lib/widget/input_complete.c +++ b/lib/widget/input_complete.c @@ -3,11 +3,12 @@ (Let mc type for you...) Copyright (C) 1995, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - 2007, 2011 + 2007, 2011, 2013 the Free Software Foundation, Inc. Written by: Jakub Jelinek, 1995 + Slava Zanko , 2013 This file is part of the Midnight Commander. @@ -79,6 +80,17 @@ extern char **environ; typedef char *CompletionFunction (const char *text, int state, input_complete_t flags); +typedef struct +{ + size_t in_command_position; + char *word; + char *p; + char *q; + char *r; + gboolean is_cd; + input_complete_t flags; +} try_complete_automation_state_t; + /*** file scope variables ************************************************************************/ static char **hosts = NULL; @@ -94,6 +106,9 @@ static int end = 0; /*** file scope functions ************************************************************************/ /* --------------------------------------------------------------------------------------------- */ +char **try_complete (char *text, int *lc_start, int *lc_end, input_complete_t flags); +void complete_engine_fill_completions (WInput * in); + #ifdef DO_COMPLETION_DEBUG /** * Useful to print/debug completion flags @@ -265,32 +280,25 @@ filename_completion_function (const char *text, int state, input_complete_t flag users_dirname = NULL; return NULL; } - else + { - char *temp; + GString *temp; - if (users_dirname && (users_dirname[0] != '.' || users_dirname[1])) + temp = g_string_sized_new (16); + + if (users_dirname != NULL && (users_dirname[0] != '.' || users_dirname[1] != '\0')) { - size_t dirlen = strlen (users_dirname); - temp = g_malloc (3 + dirlen + NLENGTH (entry)); - strcpy (temp, users_dirname); + g_string_append (temp, users_dirname); + /* We need a `/' at the end. */ - if (users_dirname[dirlen - 1] != PATH_SEP) - { - temp[dirlen] = PATH_SEP; - temp[dirlen + 1] = '\0'; - } - strcat (temp, entry->d_name); - } - else - { - temp = g_malloc (2 + NLENGTH (entry)); - strcpy (temp, entry->d_name); + if (temp->str[temp->len - 1] != PATH_SEP) + g_string_append_c (temp, PATH_SEP); } + g_string_append (temp, entry->d_name); if (isdir) - strcat (temp, PATH_SEP_STR); + g_string_append_c (temp, PATH_SEP); - return temp; + return g_string_free (temp, FALSE); } } @@ -338,7 +346,8 @@ static char * variable_completion_function (const char *text, int state, input_complete_t flags) { static char **env_p; - static int varlen, isbrace; + static unsigned int isbrace; + static size_t varlen; const char *p = NULL; (void) flags; @@ -346,7 +355,7 @@ variable_completion_function (const char *text, int state, input_complete_t flag if (state == 0) { /* Initialization stuff */ - isbrace = (text[1] == '{'); + isbrace = (text[1] == '{') ? 1 : 0; varlen = strlen (text + 1 + isbrace); env_p = environ; } @@ -354,7 +363,7 @@ variable_completion_function (const char *text, int state, input_complete_t flag while (*env_p) { p = strchr (*env_p, '='); - if (p && p - *env_p >= varlen && !strncmp (text + 1 + isbrace, *env_p, varlen)) + if (p && ((size_t) (p - *env_p) >= varlen) && !strncmp (text + 1 + isbrace, *env_p, varlen)) break; env_p++; } @@ -363,18 +372,20 @@ variable_completion_function (const char *text, int state, input_complete_t flag return NULL; { - char *temp = g_malloc (2 + 2 * isbrace + p - *env_p); + GString *temp; + + temp = g_string_new_len (*env_p, p - *env_p); + + if (isbrace != 0) + { + g_string_prepend_c (temp, '{'); + g_string_append_c (temp, '}'); + } + g_string_prepend_c (temp, '$'); - *temp = '$'; - if (isbrace) - temp[1] = '{'; - memcpy (temp + 1 + isbrace, *env_p, p - *env_p); - if (isbrace) - strcpy (temp + 2 + (p - *env_p), "}"); - else - temp[1 + p - *env_p] = 0; env_p++; - return temp; + + return g_string_free (temp, FALSE); } } @@ -441,10 +452,11 @@ fetch_hosts (const char *filename) if (hosts_p - hosts >= hosts_alloclen) { - int j = hosts_p - hosts; + int j; - hosts = - g_realloc ((void *) hosts, ((hosts_alloclen += 30) + 1) * sizeof (char *)); + j = hosts_p - hosts; + hosts_alloclen += 30; + hosts = g_renew (char *, hosts, hosts_alloclen + 1); hosts_p = hosts + j; } for (host_p = hosts; host_p < hosts_p; host_p++) @@ -469,56 +481,54 @@ static char * hostname_completion_function (const char *text, int state, input_complete_t flags) { static char **host_p; - static int textstart, textlen; + static unsigned int textstart; + static size_t textlen; (void) flags; SHOW_C_CTX ("hostname_completion_function"); - if (!state) + if (state == 0) { /* Initialization stuff */ const char *p; - if (hosts != NULL) - { - for (host_p = hosts; *host_p; host_p++) - g_free (*host_p); - g_free (hosts); - } - hosts = g_new (char *, (hosts_alloclen = 30) + 1); + g_strfreev (hosts); + hosts_alloclen = 30; + hosts = g_new (char *, hosts_alloclen + 1); *hosts = NULL; hosts_p = hosts; - fetch_hosts ((p = getenv ("HOSTFILE")) ? p : "/etc/hosts"); + p = getenv ("HOSTFILE"); + fetch_hosts (p != NULL ? p : "/etc/hosts"); host_p = hosts; textstart = (*text == '@') ? 1 : 0; textlen = strlen (text + textstart); } - while (*host_p) + for (; *host_p != NULL; host_p++) { - if (!textlen) + if (textlen == 0) break; /* Match all of them */ - else if (!strncmp (text + textstart, *host_p, textlen)) + if (strncmp (text + textstart, *host_p, textlen) == 0) break; - host_p++; } - if (!*host_p) + if (*host_p == NULL) { - for (host_p = hosts; *host_p; host_p++) - g_free (*host_p); - g_free (hosts); + g_strfreev (hosts); hosts = NULL; return NULL; } - else - { - char *temp = g_malloc (2 + strlen (*host_p)); - if (textstart) - *temp = '@'; - strcpy (temp + textstart, *host_p); + { + GString *temp; + + temp = g_string_sized_new (8); + + if (textstart != 0) + g_string_append_c (temp, '@'); + g_string_append (temp, *host_p); host_p++; - return temp; + + return g_string_free (temp, FALSE); } } @@ -598,6 +608,7 @@ command_completion_function (const char *_text, int state, input_complete_t flag if (p != NULL) { char *temp_p = p; + p = strutils_shell_escape (p); g_free (temp_p); } @@ -610,27 +621,21 @@ command_completion_function (const char *_text, int state, input_complete_t flag switch (phase) { case 0: /* Reserved words */ - while (*words) - { + for (; *words != NULL; words++) if (strncmp (*words, text, text_len) == 0) { g_free (text); return g_strdup (*(words++)); } - words++; - } phase++; words = bash_builtins; case 1: /* Builtin commands */ - while (*words) - { + for (; *words != NULL; words++) if (strncmp (*words, text, text_len) == 0) { g_free (text); return g_strdup (*(words++)); } - words++; - } phase++; if (!path) break; @@ -702,24 +707,25 @@ static char ** completion_matches (const char *text, CompletionFunction entry_function, input_complete_t flags) { /* Number of slots in match_list. */ - int match_list_size; - + size_t match_list_size = 30; /* The list of matches. */ - char **match_list = g_new (char *, (match_list_size = 30) + 1); - + char **match_list; /* Number of matches actually found. */ - int matches = 0; + size_t matches = 0; /* Temporary string binder. */ char *string; + match_list = g_new (char *, match_list_size + 1); match_list[1] = NULL; while ((string = (*entry_function) (text, matches, flags)) != NULL) { if (matches + 1 == match_list_size) - match_list = - (char **) g_realloc (match_list, ((match_list_size += 30) + 1) * sizeof (char *)); + { + match_list_size += 30; + match_list = (char **) g_renew (char *, match_list, match_list_size + 1); + } match_list[++matches] = string; match_list[matches + 1] = NULL; } @@ -728,7 +734,7 @@ completion_matches (const char *text, CompletionFunction entry_function, input_c lowest common denominator. That then becomes match_list[0]. */ if (matches) { - register int i = 1; + register size_t i = 1; int low = 4096; /* Count of max-matched characters. */ /* If only one match, just use that. */ @@ -739,7 +745,7 @@ completion_matches (const char *text, CompletionFunction entry_function, input_c } else { - int j; + size_t j; qsort (match_list + 1, matches, sizeof (char *), match_compare); @@ -819,155 +825,114 @@ check_is_cd (const char *text, int lc_start, input_complete_t flags) } /* --------------------------------------------------------------------------------------------- */ -/** Returns an array of matches, or NULL if none. */ -static char ** -try_complete (char *text, int *lc_start, int *lc_end, input_complete_t flags) + +static void +try_complete_commands_prepare (try_complete_automation_state_t * state, char *text, int *lc_start) { - size_t in_command_position = 0; - char *word; - char **matches = NULL; - char *p = NULL, *q = NULL, *r = NULL; - gboolean is_cd; + const char *command_separator_chars = ";|&{(`"; + char *ti; - SHOW_C_CTX ("try_complete"); - word = g_strndup (text + *lc_start, *lc_end - *lc_start); - - is_cd = check_is_cd (text, *lc_start, flags); - - /* Determine if this could be a command word. It is if it appears at - the start of the line (ignoring preceding whitespace), or if it - appears after a character that separates commands. And we have to - be in a INPUT_COMPLETE_COMMANDS flagged Input line. */ - if (!is_cd && (flags & INPUT_COMPLETE_COMMANDS)) + if (*lc_start == 0) + ti = text; + else { - const char *command_separator_chars = ";|&{(`"; - char *ti; - - if (*lc_start == 0) - ti = text; - else - { - ti = str_get_prev_char (&text[*lc_start]); - while (ti > text && (ti[0] == ' ' || ti[0] == '\t')) - str_prev_char (&ti); - } - - if (ti == text) - in_command_position++; - else if (strchr (command_separator_chars, ti[0]) != NULL) - { - int this_char, prev_char; - - in_command_position++; - - if (ti != text) - { - /* Handle the two character tokens `>&', `<&', and `>|'. - We are not in a command position after one of these. */ - this_char = ti[0]; - prev_char = str_get_prev_char (ti)[0]; - - /* Quoted */ - if ((this_char == '&' && (prev_char == '<' || prev_char == '>')) - || (this_char == '|' && prev_char == '>') || (ti != text - && str_get_prev_char (ti)[0] == - '\\')) - in_command_position = 0; - } - } + ti = str_get_prev_char (&text[*lc_start]); + while (ti > text && (ti[0] == ' ' || ti[0] == '\t')) + str_prev_char (&ti); } - if (flags & INPUT_COMPLETE_COMMANDS) - p = strrchr (word, '`'); - if (flags & (INPUT_COMPLETE_COMMANDS | INPUT_COMPLETE_VARIABLES)) + if (ti == text) + state->in_command_position++; + else if (strchr (command_separator_chars, ti[0]) != NULL) { - q = strrchr (word, '$'); + int this_char, prev_char; + + state->in_command_position++; + + if (ti != text) + { + /* Handle the two character tokens `>&', `<&', and `>|'. + We are not in a command position after one of these. */ + this_char = ti[0]; + prev_char = str_get_prev_char (ti)[0]; + + /* Quoted */ + if ((this_char == '&' && (prev_char == '<' || prev_char == '>')) + || (this_char == '|' && prev_char == '>') || (ti != text + && str_get_prev_char (ti)[0] == '\\')) + state->in_command_position = 0; + } + } +} + +/* --------------------------------------------------------------------------------------------- */ + +static void +try_complete_find_start_sign (try_complete_automation_state_t * state) +{ + if (state->flags & INPUT_COMPLETE_COMMANDS) + state->p = strrchr (state->word, '`'); + if (state->flags & (INPUT_COMPLETE_COMMANDS | INPUT_COMPLETE_VARIABLES)) + { + state->q = strrchr (state->word, '$'); /* don't substitute variable in \$ case */ - if (q != NULL && q != word && q[-1] == '\\') + if (strutils_is_char_escaped (state->word, state->q)) { size_t qlen; - qlen = strlen (q); + qlen = strlen (state->q); /* drop '\\' */ - memmove (q - 1, q, qlen + 1); + memmove (state->q - 1, state->q, qlen + 1); /* adjust flags */ - flags &= ~INPUT_COMPLETE_VARIABLES; - q = NULL; + state->flags &= ~INPUT_COMPLETE_VARIABLES; + state->q = NULL; } } - if (flags & INPUT_COMPLETE_HOSTNAMES) - r = strrchr (word, '@'); - if (q && q[1] == '(' && (flags & INPUT_COMPLETE_COMMANDS)) + if (state->flags & INPUT_COMPLETE_HOSTNAMES) + state->r = strrchr (state->word, '@'); + if (state->q && state->q[1] == '(' && (state->flags & INPUT_COMPLETE_COMMANDS)) { - if (q > p) - p = str_get_next_char (q); - q = NULL; + if (state->q > state->p) + state->p = str_get_next_char (state->q); + state->q = NULL; } +} - /* Command substitution? */ - if (p > q && p > r) - { - SHOW_C_CTX ("try_complete:cmd_backq_subst"); - matches = completion_matches (str_cget_next_char (p), - command_completion_function, - flags & (~INPUT_COMPLETE_FILENAMES)); - if (matches) - *lc_start += str_get_next_char (p) - word; - } +/* --------------------------------------------------------------------------------------------- */ - /* Variable name? */ - else if (q > p && q > r) - { - SHOW_C_CTX ("try_complete:var_subst"); - matches = completion_matches (q, variable_completion_function, flags); - if (matches) - *lc_start += q - word; - } +static char ** +try_complete_all_possible (try_complete_automation_state_t * state, char *text, int *lc_start) +{ + char **matches = NULL; - /* Starts with '@', then look through the known hostnames for - completion first. */ - else if (r > p && r > q) - { - SHOW_C_CTX ("try_complete:host_subst"); - matches = completion_matches (r, hostname_completion_function, flags); - if (matches) - *lc_start += r - word; - } - - /* Starts with `~' and there is no slash in the word, then - try completing this word as a username. */ - if (!matches && *word == '~' && (flags & INPUT_COMPLETE_USERNAMES) && !strchr (word, PATH_SEP)) - { - SHOW_C_CTX ("try_complete:user_subst"); - matches = completion_matches (word, username_completion_function, flags); - } - - - /* And finally if this word is in a command position, then - complete over possible command names, including aliases, functions, - and command names. */ - if (!matches && in_command_position != 0) + if (state->in_command_position != 0) { SHOW_C_CTX ("try_complete:cmd_subst"); matches = - completion_matches (word, command_completion_function, - flags & (~INPUT_COMPLETE_FILENAMES)); + completion_matches (state->word, command_completion_function, + state->flags & (~INPUT_COMPLETE_FILENAMES)); } - - else if (!matches && (flags & INPUT_COMPLETE_FILENAMES)) + else if ((state->flags & INPUT_COMPLETE_FILENAMES) != 0) { - if (is_cd) - flags &= ~(INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_COMMANDS); + if (state->is_cd) + state->flags &= ~(INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_COMMANDS); SHOW_C_CTX ("try_complete:filename_subst_1"); - matches = completion_matches (word, filename_completion_function, flags); - if (!matches && is_cd && *word != PATH_SEP && *word != '~') + matches = completion_matches (state->word, filename_completion_function, state->flags); + + if (matches == NULL && state->is_cd && *state->word != PATH_SEP && *state->word != '~') { - q = text + *lc_start; - for (p = text; *p && p < q && (*p == ' ' || *p == '\t'); str_next_char (&p)); - if (!strncmp (p, "cd", 2)) - for (p += 2; *p && p < q && (*p == ' ' || *p == '\t'); str_next_char (&p)); - if (p == q) + state->q = text + *lc_start; + for (state->p = text; + *state->p && state->p < state->q && (*state->p == ' ' || *state->p == '\t'); + str_next_char (&state->p)) + ; + if (!strncmp (state->p, "cd", 2)) + for (state->p += 2; + *state->p && state->p < state->q && (*state->p == ' ' || *state->p == '\t'); + str_next_char (&state->p)) + ; + if (state->p == state->q) { char *const cdpath_ref = g_strdup (getenv ("CDPATH")); char *cdpath = cdpath_ref; @@ -986,10 +951,12 @@ try_complete (char *text, int *lc_start, int *lc_end, input_complete_t flags) *s = 0; if (*cdpath) { - r = mc_build_filename (cdpath, word, NULL); + state->r = mc_build_filename (cdpath, state->word, NULL); SHOW_C_CTX ("try_complete:filename_subst_2"); - matches = completion_matches (r, filename_completion_function, flags); - g_free (r); + matches = + completion_matches (state->r, filename_completion_function, + state->flags); + g_free (state->r); } *s = c; cdpath = str_get_next_char (s); @@ -998,24 +965,24 @@ try_complete (char *text, int *lc_start, int *lc_end, input_complete_t flags) } } } - - g_free (word); - return matches; } /* --------------------------------------------------------------------------------------------- */ -static int +static gboolean insert_text (WInput * in, char *text, ssize_t size) { - int buff_len = str_length (in->buffer); + int buff_len; + buff_len = str_length (in->buffer); size = min (size, (ssize_t) strlen (text)) + start - end; if (strlen (in->buffer) + size >= (size_t) in->current_max_size) { /* Expand the buffer */ - char *narea = g_try_realloc (in->buffer, in->current_max_size + size + in->field_width); + char *narea; + + narea = g_try_realloc (in->buffer, in->current_max_size + size + in->field_width); if (narea != NULL) { in->buffer = narea; @@ -1024,20 +991,9 @@ insert_text (WInput * in, char *text, ssize_t size) } if (strlen (in->buffer) + 1 < (size_t) in->current_max_size) { - if (size > 0) - { - int i = strlen (&in->buffer[end]); - for (; i >= 0; i--) - in->buffer[end + size + i] = in->buffer[end + i]; - } - else if (size < 0) - { - char *p = in->buffer + end + size, *q = in->buffer + end; - while (*q) - *(p++) = *(q++); - *p = 0; - } - memcpy (in->buffer + start, text, size - start + end); + if (size != 0) + memmove (in->buffer + end + size, in->buffer + end, strlen (&in->buffer[end]) + 1); + memmove (in->buffer + start, text, size - (start - end)); in->point += str_length (in->buffer) - buff_len; input_update (in, TRUE); end += size; @@ -1224,43 +1180,16 @@ query_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void *d } /* --------------------------------------------------------------------------------------------- */ -/** Returns 1 if the user would like to see us again */ +/** Returns 1 if the user would like to see us again */ static int complete_engine (WInput * in, int what_to_do) { if (in->completions != NULL && str_offset_to_pos (in->buffer, in->point) != end) input_free_completions (in); + if (in->completions == NULL) - { - char *s; - - end = str_offset_to_pos (in->buffer, in->point); - - s = in->buffer; - if (in->point != 0) - { - /* get symbol before in->point */ - size_t i; - for (i = in->point - 1; i > 0; i--) - str_next_char (&s); - } - - for (; s >= in->buffer; str_prev_char (&s)) - { - start = s - in->buffer; - if (strchr (" \t;|<>", *s) != NULL) - break; - } - - if (start < end) - { - str_next_char (&s); - start = s - in->buffer; - } - - in->completions = try_complete (in->buffer, &start, &end, in->completion_flags); - } + complete_engine_fill_completions (in); if (in->completions != NULL) { @@ -1356,6 +1285,120 @@ complete_engine (WInput * in, int what_to_do) /*** public functions ****************************************************************************/ /* --------------------------------------------------------------------------------------------- */ +/** Returns an array of matches, or NULL if none. */ +char ** +try_complete (char *text, int *lc_start, int *lc_end, input_complete_t flags) +{ + try_complete_automation_state_t state; + char **matches = NULL; + + memset (&state, 0, sizeof (try_complete_automation_state_t)); + state.flags = flags; + + SHOW_C_CTX ("try_complete"); + state.word = g_strndup (text + *lc_start, *lc_end - *lc_start); + + state.is_cd = check_is_cd (text, *lc_start, state.flags); + + /* Determine if this could be a command word. It is if it appears at + the start of the line (ignoring preceding whitespace), or if it + appears after a character that separates commands. And we have to + be in a INPUT_COMPLETE_COMMANDS flagged Input line. */ + if (!state.is_cd && (flags & INPUT_COMPLETE_COMMANDS)) + try_complete_commands_prepare (&state, text, lc_start); + + try_complete_find_start_sign (&state); + + /* Command substitution? */ + if (state.p > state.q && state.p > state.r) + { + SHOW_C_CTX ("try_complete:cmd_backq_subst"); + matches = completion_matches (str_cget_next_char (state.p), + command_completion_function, + state.flags & (~INPUT_COMPLETE_FILENAMES)); + if (matches) + *lc_start += str_get_next_char (state.p) - state.word; + } + + /* Variable name? */ + else if (state.q > state.p && state.q > state.r) + { + SHOW_C_CTX ("try_complete:var_subst"); + matches = completion_matches (state.q, variable_completion_function, state.flags); + if (matches) + *lc_start += state.q - state.word; + } + + /* Starts with '@', then look through the known hostnames for + completion first. */ + else if (state.r > state.p && state.r > state.q) + { + SHOW_C_CTX ("try_complete:host_subst"); + matches = completion_matches (state.r, hostname_completion_function, state.flags); + if (matches) + *lc_start += state.r - state.word; + } + + /* Starts with `~' and there is no slash in the word, then + try completing this word as a username. */ + if (!matches && *state.word == '~' && (state.flags & INPUT_COMPLETE_USERNAMES) + && !strchr (state.word, PATH_SEP)) + { + SHOW_C_CTX ("try_complete:user_subst"); + matches = completion_matches (state.word, username_completion_function, state.flags); + } + + /* And finally if this word is in a command position, then + complete over possible command names, including aliases, functions, + and command names. */ + if (matches == NULL) + matches = try_complete_all_possible (&state, text, lc_start); + + g_free (state.word); + + return matches; +} + +/* --------------------------------------------------------------------------------------------- */ + +void +complete_engine_fill_completions (WInput * in) +{ + char *s; + const char *word_separators; + + word_separators = (in->completion_flags & INPUT_COMPLETE_SHELL_ESC) ? " \t;|<>" : "\t;|<>"; + + end = str_offset_to_pos (in->buffer, in->point); + + s = in->buffer; + if (in->point != 0) + { + /* get symbol before in->point */ + size_t i; + + for (i = in->point - 1; i > 0; i--) + str_next_char (&s); + } + + for (; s >= in->buffer; str_prev_char (&s)) + { + start = s - in->buffer; + if (strchr (word_separators, *s) != NULL && !strutils_is_char_escaped (in->buffer, s)) + break; + } + + if (start < end) + { + str_next_char (&s); + start = s - in->buffer; + } + + in->completions = try_complete (in->buffer, &start, &end, in->completion_flags); +} + +/* --------------------------------------------------------------------------------------------- */ + /* declared in lib/widget/input.h */ void complete (WInput * in) diff --git a/lib/widget/quick.c b/lib/widget/quick.c index e3c42fb5b..790915b33 100644 --- a/lib/widget/quick.c +++ b/lib/widget/quick.c @@ -72,12 +72,10 @@ quick_create_input (int y, int x, const quick_widget_t * qw) WInput *in; in = input_new (y, x, input_get_default_colors (), 8, qw->u.input.text, qw->u.input.histname, - INPUT_COMPLETE_DEFAULT); - in->is_password = (qw->u.input.flags == 1); - if ((qw->u.input.flags & 2) != 0) - in->completion_flags |= INPUT_COMPLETE_CD; - if ((qw->u.input.flags & 4) != 0) - in->strip_password = TRUE; + qw->u.input.completion_flags); + + in->is_password = qw->u.input.is_passwd; + in->strip_password = qw->u.input.strip_passwd; return in; } @@ -587,7 +585,7 @@ quick_dialog_skip (quick_dialog_t * quick_dlg, int nskip) break; case quick_input: - if ((quick_widget->u.input.flags & 2) != 0) + if ((quick_widget->u.input.completion_flags & INPUT_COMPLETE_CD) != 0) *item->quick_widget->u.input.result = tilde_expand (INPUT (item->widget)->buffer); else diff --git a/lib/widget/quick.h b/lib/widget/quick.h index a88763aa3..73482d627 100644 --- a/lib/widget/quick.h +++ b/lib/widget/quick.h @@ -38,7 +38,7 @@ } \ } -#define QUICK_INPUT(txt, flags_, hname, res, id_) \ +#define QUICK_INPUT(txt, hname, res, id_, is_passwd_, strip_passwd_, completion_flags_) \ { \ .widget_type = quick_input, \ .options = 0, \ @@ -50,14 +50,16 @@ .label_location = input_label_none, \ .label = NULL, \ .text = txt, \ - .flags = flags_, \ + .completion_flags = completion_flags_, \ + .is_passwd = is_passwd_, \ + .strip_passwd = strip_passwd_, \ .histname = hname, \ .result = res \ } \ } \ } -#define QUICK_LABELED_INPUT(label_, label_loc, txt, flags_, hname, res, id_) \ +#define QUICK_LABELED_INPUT(label_, label_loc, txt, hname, res, id_, is_passwd_, strip_passwd_, completion_flags_) \ { \ .widget_type = quick_input, \ .options = 0, \ @@ -69,7 +71,9 @@ .label_location = label_loc, \ .label = NULL, \ .text = txt, \ - .flags = flags_, \ + .completion_flags = completion_flags_, \ + .is_passwd = is_passwd_, \ + .strip_passwd = strip_passwd_, \ .histname = hname, \ .result = res \ } \ @@ -127,7 +131,6 @@ .u = { \ .input = { \ .text = NULL, \ - .flags = 0, \ .histname = NULL, \ .result = NULL \ } \ @@ -157,7 +160,6 @@ .u = { \ .input = { \ .text = NULL, \ - .flags = 0, \ .histname = NULL, \ .result = NULL \ } \ @@ -173,7 +175,6 @@ .u = { \ .input = { \ .text = NULL, \ - .flags = 0, \ .histname = NULL, \ .result = NULL \ } \ @@ -189,7 +190,6 @@ .u = { \ .input = { \ .text = NULL, \ - .flags = 0, \ .histname = NULL, \ .result = NULL \ } \ @@ -224,7 +224,6 @@ .u = { \ .input = { \ .text = NULL, \ - .flags = 0, \ .histname = NULL, \ .result = NULL \ } \ @@ -295,10 +294,11 @@ struct quick_widget_t quick_input_label_location_t label_location; quick_widget_t *label; const char *text; - int flags; /* 1 -- is_password, 2 -- INPUT_COMPLETE_CD */ + input_complete_t completion_flags; + gboolean is_passwd; /* TRUE -- is password */ + gboolean strip_passwd; const char *histname; char **result; - gboolean strip_password; } input; struct diff --git a/lib/widget/wtools.c b/lib/widget/wtools.c index e01d05c30..274827cd5 100644 --- a/lib/widget/wtools.c +++ b/lib/widget/wtools.c @@ -182,11 +182,12 @@ bg_message (int dummy, int *flags, char *title, const char *text) */ static char * fg_input_dialog_help (const char *header, const char *text, const char *help, - const char *history_name, const char *def_text, gboolean strip_password) + const char *history_name, const char *def_text, gboolean strip_password, + input_complete_t completion_flags) { char *p_text; char histname[64] = "inp|"; - int flags = strip_password ? 4 : 0; + gboolean is_passwd = FALSE; char *my_str; int ret; @@ -201,7 +202,7 @@ fg_input_dialog_help (const char *header, const char *text, const char *help, and hide characters with "*". Don't save passwords in history! */ if (def_text == INPUT_PASSWORD) { - flags = 1; + is_passwd = TRUE; histname[3] = '\0'; def_text = ""; } @@ -209,8 +210,8 @@ fg_input_dialog_help (const char *header, const char *text, const char *help, { quick_widget_t quick_widgets[] = { /* *INDENT-OFF* */ - QUICK_LABELED_INPUT (p_text, input_label_above, def_text, flags, histname, &my_str, - NULL), + QUICK_LABELED_INPUT (p_text, input_label_above, def_text, histname, &my_str, + NULL, is_passwd, strip_password, completion_flags), QUICK_BUTTONS_OK_CANCEL, QUICK_END /* *INDENT-ON* */ @@ -440,7 +441,8 @@ message (int flags, const char *title, const char *text, ...) char * input_dialog_help (const char *header, const char *text, const char *help, - const char *history_name, const char *def_text, gboolean strip_password) + const char *history_name, const char *def_text, gboolean strip_password, + input_complete_t completion_flags) { #ifdef ENABLE_BACKGROUND if (mc_global.we_are_background) @@ -449,40 +451,45 @@ input_dialog_help (const char *header, const char *text, const char *help, { void *p; char *(*f) (const char *, const char *, const char *, const char *, const char *, - gboolean); + gboolean, input_complete_t); } func; func.f = fg_input_dialog_help; - return wtools_parent_call_string (func.p, 6, + return wtools_parent_call_string (func.p, 7, strlen (header), header, strlen (text), text, strlen (help), help, strlen (history_name), history_name, strlen (def_text), def_text, - sizeof (gboolean), strip_password); + sizeof (gboolean), strip_password, + sizeof (input_complete_t), completion_flags); } else #endif /* ENABLE_BACKGROUND */ - return fg_input_dialog_help (header, text, help, history_name, def_text, strip_password); + return fg_input_dialog_help (header, text, help, history_name, def_text, strip_password, + completion_flags); } /* --------------------------------------------------------------------------------------------- */ /** Show input dialog with default help, background safe */ char * -input_dialog (const char *header, const char *text, const char *history_name, const char *def_text) +input_dialog (const char *header, const char *text, const char *history_name, const char *def_text, + input_complete_t completion_flags) { - return input_dialog_help (header, text, "[Input Line Keys]", history_name, def_text, FALSE); + return input_dialog_help (header, text, "[Input Line Keys]", history_name, def_text, FALSE, + completion_flags); } /* --------------------------------------------------------------------------------------------- */ char * input_expand_dialog (const char *header, const char *text, - const char *history_name, const char *def_text) + const char *history_name, const char *def_text, + input_complete_t completion_flags) { char *result; char *expanded; - result = input_dialog (header, text, history_name, def_text); + result = input_dialog (header, text, history_name, def_text, completion_flags); if (result) { expanded = tilde_expand (result); diff --git a/lib/widget/wtools.h b/lib/widget/wtools.h index 4e23e9ce6..06704f86c 100644 --- a/lib/widget/wtools.h +++ b/lib/widget/wtools.h @@ -31,11 +31,13 @@ enum /* The input dialogs */ char *input_dialog (const char *header, const char *text, - const char *history_name, const char *def_text); + const char *history_name, const char *def_text, + input_complete_t completion_flags); char *input_dialog_help (const char *header, const char *text, const char *help, - const char *history_name, const char *def_text, gboolean strip_password); -char *input_expand_dialog (const char *header, const char *text, - const char *history_name, const char *def_text); + const char *history_name, const char *def_text, gboolean strip_password, + input_complete_t completion_flags); +char *input_expand_dialog (const char *header, const char *text, const char *history_name, + const char *def_text, input_complete_t completion_flags); int query_dialog (const char *header, const char *text, int flags, int count, ...); void query_set_sel (int new_sel); diff --git a/src/diffviewer/search.c b/src/diffviewer/search.c index 902a5a973..19176af69 100644 --- a/src/diffviewer/search.c +++ b/src/diffviewer/search.c @@ -82,8 +82,8 @@ mcdiffview_dialog_search (WDiff * dview) { quick_widget_t quick_widgets[] = { /* *INDENT-OFF* */ - QUICK_LABELED_INPUT (N_("Enter search string:"), input_label_above, - INPUT_LAST_TEXT, 0, MC_HISTORY_SHARED_SEARCH, &exp, NULL), + QUICK_LABELED_INPUT (N_("Enter search string:"), input_label_above, INPUT_LAST_TEXT, + MC_HISTORY_SHARED_SEARCH, &exp, NULL, FALSE, FALSE, INPUT_COMPLETE_NONE), QUICK_SEPARATOR (TRUE), QUICK_START_COLUMNS, QUICK_RADIO (num_of_types, (const char **) list_of_types, diff --git a/src/diffviewer/ydiff.c b/src/diffviewer/ydiff.c index 2fd6f1c48..59e1dd884 100644 --- a/src/diffviewer/ydiff.c +++ b/src/diffviewer/ydiff.c @@ -2908,7 +2908,9 @@ dview_goto_cmd (WDiff * dview, diff_place_t ord) int newline; char *input; - input = input_dialog (_(title[ord]), _("Enter line:"), MC_HISTORY_YDIFF_GOTO_LINE, prev); + input = + input_dialog (_(title[ord]), _("Enter line:"), MC_HISTORY_YDIFF_GOTO_LINE, prev, + INPUT_COMPLETE_NONE); if (input != NULL) { const char *s = input; diff --git a/src/editor/editcmd.c b/src/editor/editcmd.c index e170e0652..0b7c70ae4 100644 --- a/src/editor/editcmd.c +++ b/src/editor/editcmd.c @@ -462,8 +462,8 @@ edit_get_save_file_as (WEdit * edit) { quick_widget_t quick_widgets[] = { /* *INDENT-OFF* */ - QUICK_LABELED_INPUT (N_("Enter file name:"), input_label_above, filename, 0, "save-as", - &filename_res, NULL), + QUICK_LABELED_INPUT (N_("Enter file name:"), input_label_above, filename, "save-as", + &filename_res, NULL, FALSE, FALSE, INPUT_COMPLETE_FILENAMES), QUICK_SEPARATOR (TRUE), QUICK_LABEL (N_("Change line breaks to:"), NULL), QUICK_RADIO (LB_NAMES, lb_names, (int *) &cur_lb, NULL), @@ -1602,8 +1602,8 @@ edit_save_mode_cmd (void) quick_widget_t quick_widgets[] = { /* *INDENT-OFF* */ QUICK_RADIO (3, str, &option_save_mode, &edit_save_mode_radio_id), - QUICK_INPUT (option_backup_ext, 0, "edit-backup-ext", &str_result, - &edit_save_mode_input_id), + QUICK_INPUT (option_backup_ext, "edit-backup-ext", &str_result, + &edit_save_mode_input_id, FALSE, FALSE, INPUT_COMPLETE_NONE), QUICK_SEPARATOR (TRUE), QUICK_CHECKBOX (N_("Check &POSIX new line"), &option_check_nl_at_eof, NULL), QUICK_BUTTONS_OK_CANCEL, @@ -1897,7 +1897,8 @@ edit_repeat_macro_cmd (WEdit * edit) long count_repeat; char *error = NULL; - f = input_dialog (_("Repeat last commands"), _("Repeat times:"), MC_HISTORY_EDIT_REPEAT, NULL); + f = input_dialog (_("Repeat last commands"), _("Repeat times:"), MC_HISTORY_EDIT_REPEAT, NULL, + INPUT_COMPLETE_NONE); if (f == NULL || *f == '\0') { g_free (f); @@ -2063,7 +2064,8 @@ edit_load_cmd (WDialog * h) gboolean ret = TRUE; /* possible cancel */ exp = input_expand_dialog (_("Load"), _("Enter file name:"), - MC_HISTORY_EDIT_LOAD, INPUT_LAST_TEXT); + MC_HISTORY_EDIT_LOAD, INPUT_LAST_TEXT, + INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_CD); if (exp != NULL && *exp != '\0') { @@ -3058,7 +3060,8 @@ edit_goto_cmd (WEdit * edit) char s[32]; g_snprintf (s, sizeof (s), "%ld", line); - f = input_dialog (_("Goto line"), _("Enter line:"), MC_HISTORY_EDIT_GOTO_LINE, line ? s : ""); + f = input_dialog (_("Goto line"), _("Enter line:"), MC_HISTORY_EDIT_GOTO_LINE, line ? s : "", + INPUT_COMPLETE_NONE); if (!f) return; @@ -3101,7 +3104,7 @@ edit_save_block_cmd (WEdit * edit) tmp = mc_config_get_full_path (EDIT_CLIP_FILE); exp = input_expand_dialog (_("Save block"), _("Enter file name:"), - MC_HISTORY_EDIT_SAVE_BLOCK, tmp); + MC_HISTORY_EDIT_SAVE_BLOCK, tmp, INPUT_COMPLETE_FILENAMES); g_free (tmp); edit_push_undo_action (edit, KEY_PRESS + edit->start_display); @@ -3133,7 +3136,7 @@ edit_insert_file_cmd (WEdit * edit) tmp = mc_config_get_full_path (EDIT_CLIP_FILE); exp = input_expand_dialog (_("Insert file"), _("Enter file name:"), - MC_HISTORY_EDIT_INSERT_FILE, tmp); + MC_HISTORY_EDIT_INSERT_FILE, tmp, INPUT_COMPLETE_FILENAMES); g_free (tmp); edit_push_undo_action (edit, KEY_PRESS + edit->start_display); @@ -3179,7 +3182,7 @@ edit_sort_cmd (WEdit * edit) exp = input_dialog (_("Run sort"), _("Enter sort options (see manpage) separated by whitespace:"), - MC_HISTORY_EDIT_SORT, (old != NULL) ? old : ""); + MC_HISTORY_EDIT_SORT, (old != NULL) ? old : "", INPUT_COMPLETE_NONE); if (!exp) return 1; @@ -3241,7 +3244,10 @@ edit_ext_cmd (WEdit * edit) exp = input_dialog (_("Paste output of external command"), - _("Enter shell command(s):"), MC_HISTORY_EDIT_PASTE_EXTCMD, NULL); + _("Enter shell command(s):"), MC_HISTORY_EDIT_PASTE_EXTCMD, NULL, + INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_VARIABLES | INPUT_COMPLETE_USERNAMES + | INPUT_COMPLETE_HOSTNAMES | INPUT_COMPLETE_CD | INPUT_COMPLETE_COMMANDS | + INPUT_COMPLETE_SHELL_ESC); if (!exp) return 1; @@ -3308,14 +3314,14 @@ edit_mail_dialog (WEdit * edit) /* *INDENT-OFF* */ QUICK_LABEL (N_("mail -s -c "), NULL), QUICK_LABELED_INPUT (N_("To"), input_label_above, - mail_to_last != NULL ? mail_to_last : "", 0, - "mail-dlg-input-3", &tmail_to, NULL), + mail_to_last != NULL ? mail_to_last : "", "mail-dlg-input-3", + &tmail_to, NULL, FALSE, FALSE, INPUT_COMPLETE_USERNAMES), QUICK_LABELED_INPUT (N_("Subject"), input_label_above, - mail_subject_last != NULL ? mail_subject_last : "", 0, - "mail-dlg-input-2", &tmail_subject, NULL), + mail_subject_last != NULL ? mail_subject_last : "", "mail-dlg-input-2", + &tmail_subject, NULL, FALSE, FALSE, INPUT_COMPLETE_NONE), QUICK_LABELED_INPUT (N_("Copies to"), input_label_above, - mail_cc_last != NULL ? mail_cc_last : "", 0, - "mail-dlg-input", &tmail_cc, NULL), + mail_cc_last != NULL ? mail_cc_last : "", "mail-dlg-input", + &tmail_cc, NULL, FALSE, FALSE, INPUT_COMPLETE_USERNAMES), QUICK_BUTTONS_OK_CANCEL, QUICK_END /* *INDENT-ON* */ diff --git a/src/editor/editcmd_dialogs.c b/src/editor/editcmd_dialogs.c index aa9f14523..e70620153 100644 --- a/src/editor/editcmd_dialogs.c +++ b/src/editor/editcmd_dialogs.c @@ -101,8 +101,9 @@ editcmd_dialog_search_show (WEdit * edit) { quick_widget_t quick_widgets[] = { /* *INDENT-OFF* */ - QUICK_LABELED_INPUT (N_("Enter search string:"), input_label_above, - INPUT_LAST_TEXT, 0, MC_HISTORY_SHARED_SEARCH, &search_text, NULL), + QUICK_LABELED_INPUT (N_("Enter search string:"), input_label_above, INPUT_LAST_TEXT, + MC_HISTORY_SHARED_SEARCH, &search_text, NULL, FALSE, FALSE, + INPUT_COMPLETE_NONE), QUICK_SEPARATOR (TRUE), QUICK_START_COLUMNS, QUICK_RADIO (num_of_types, (const char **) list_of_types, @@ -191,10 +192,11 @@ editcmd_dialog_replace_show (WEdit * edit, const char *search_default, const cha { quick_widget_t quick_widgets[] = { /* *INDENT-OFF* */ - QUICK_LABELED_INPUT (N_("Enter search string:"), input_label_above, - search_default, 0, MC_HISTORY_SHARED_SEARCH, search_text, NULL), - QUICK_LABELED_INPUT (N_("Enter replacement string:"), input_label_above, - replace_default, 0, "replace", replace_text, NULL), + QUICK_LABELED_INPUT (N_("Enter search string:"), input_label_above, search_default, + MC_HISTORY_SHARED_SEARCH, search_text, NULL, FALSE, FALSE, + INPUT_COMPLETE_NONE), + QUICK_LABELED_INPUT (N_("Enter replacement string:"), input_label_above, replace_default, + "replace", replace_text, NULL, FALSE, FALSE, INPUT_COMPLETE_NONE), QUICK_SEPARATOR (TRUE), QUICK_START_COLUMNS, QUICK_RADIO (num_of_types, (const char **) list_of_types, @@ -316,7 +318,7 @@ editcmd_dialog_raw_key_query (const char *heading, const char *query, gboolean c add_widget (raw_dlg, label_new (y, 3, query)); add_widget (raw_dlg, input_new (y++, 3 + wq + 1, input_get_default_colors (), - w - (6 + wq + 1), "", 0, INPUT_COMPLETE_DEFAULT)); + w - (6 + wq + 1), "", 0, INPUT_COMPLETE_NONE)); if (cancel) { add_widget (raw_dlg, hline_new (y++, -1, -1)); diff --git a/src/editor/editoptions.c b/src/editor/editoptions.c index 3e0cf7bff..0c315c72a 100644 --- a/src/editor/editoptions.c +++ b/src/editor/editoptions.c @@ -156,8 +156,8 @@ edit_options_dialog (WDialog * h) NULL), QUICK_CHECKBOX (N_("Fill tabs with &spaces"), &option_fill_tabs_with_spaces, NULL), - QUICK_LABELED_INPUT (N_("Tab spacing:"), input_label_left, tab_spacing, 0, - "edit-tab-spacing", &q, NULL), + QUICK_LABELED_INPUT (N_("Tab spacing:"), input_label_left, tab_spacing, + "edit-tab-spacing", &q, NULL, FALSE, FALSE, INPUT_COMPLETE_NONE), QUICK_STOP_GROUPBOX, QUICK_NEXT_COLUMN, QUICK_START_GROUPBOX (N_("Other options")), @@ -174,8 +174,8 @@ edit_options_dialog (WDialog * h) QUICK_CHECKBOX (N_("Cursor be&yond end of line"), &option_cursor_beyond_eol, NULL), QUICK_CHECKBOX (N_("&Group undo"), &option_group_undo, NULL), - QUICK_LABELED_INPUT (N_("Word wrap line length:"), input_label_left, - wrap_length, 0, "edit-word-wrap", &p, NULL), + QUICK_LABELED_INPUT (N_("Word wrap line length:"), input_label_left, wrap_length, + "edit-word-wrap", &p, NULL, FALSE, FALSE, INPUT_COMPLETE_NONE), QUICK_STOP_GROUPBOX, QUICK_STOP_COLUMNS, QUICK_BUTTONS_OK_CANCEL, diff --git a/src/filemanager/boxes.c b/src/filemanager/boxes.c index c11dfb788..1b152672c 100644 --- a/src/filemanager/boxes.c +++ b/src/filemanager/boxes.c @@ -464,8 +464,9 @@ configure_box (void) QUICK_START_GROUPBOX (N_("Esc key mode")), QUICK_CHECKBOX (N_("S&ingle press"), &old_esc_mode, &configure_old_esc_mode_id), QUICK_LABELED_INPUT (N_("Timeout:"), input_label_left, - (const char *) time_out, 0, MC_HISTORY_ESC_TIMEOUT, - &time_out_new, &configure_time_out_id), + (const char *) time_out, MC_HISTORY_ESC_TIMEOUT, + &time_out_new, &configure_time_out_id, FALSE, FALSE, + INPUT_COMPLETE_NONE), QUICK_STOP_GROUPBOX, QUICK_START_GROUPBOX (N_("Pause after run")), QUICK_RADIO (pause_options_num, pause_options, &pause_after_run, NULL), @@ -653,12 +654,12 @@ panel_listing_box (WPanel * panel, char **userp, char **minip, int *use_msformat quick_widget_t quick_widgets[] = { /* *INDENT-OFF* */ QUICK_RADIO (LIST_TYPES, list_types, &result, &panel_listing_types_id), - QUICK_INPUT (panel->user_format, INPUT_COMPLETE_DEFAULT, "user-fmt-input", - &panel_user_format, &panel_user_format_id), + QUICK_INPUT (panel->user_format, "user-fmt-input", &panel_user_format, + &panel_user_format_id, FALSE, FALSE, INPUT_COMPLETE_NONE), QUICK_SEPARATOR (TRUE), QUICK_CHECKBOX (N_("User &mini status"), &mini_user_status, &mini_user_status_id), - QUICK_INPUT (panel->user_status_format[panel->list_type], INPUT_COMPLETE_DEFAULT, - "mini_input", &mini_user_format, &mini_user_format_id), + QUICK_INPUT (panel->user_status_format[panel->list_type], "mini_input", + &mini_user_format, &mini_user_format_id, FALSE, FALSE, INPUT_COMPLETE_NONE), QUICK_BUTTONS_OK_CANCEL, QUICK_END /* *INDENT-ON* */ @@ -974,17 +975,20 @@ configure_vfs (void) quick_widget_t quick_widgets[] = { /* *INDENT-OFF* */ QUICK_LABELED_INPUT (N_("Timeout for freeing VFSs (sec):"), input_label_left, - buffer2, 0, "input-timo-vfs", &ret_timeout, NULL), + buffer2, "input-timo-vfs", &ret_timeout, NULL, FALSE, FALSE, + INPUT_COMPLETE_NONE), #ifdef ENABLE_VFS_FTP QUICK_SEPARATOR (TRUE), QUICK_LABELED_INPUT (N_("FTP anonymous password:"), input_label_left, - ftpfs_anonymous_passwd, 0, "input-passwd", &ret_passwd, NULL), + ftpfs_anonymous_passwd, "input-passwd", &ret_passwd, NULL, + FALSE, FALSE, INPUT_COMPLETE_NONE), QUICK_LABELED_INPUT (N_("FTP directory cache timeout (sec):"), input_label_left, - buffer3, 0, "input-timeout", &ret_directory_timeout, NULL), + buffer3, "input-timeout", &ret_directory_timeout, NULL, + FALSE, FALSE, INPUT_COMPLETE_NONE), QUICK_CHECKBOX (N_("&Always use ftp proxy:"), &ftpfs_always_use_proxy, &ftpfs_always_use_proxy_id), - QUICK_INPUT (ftpfs_proxy_host, 0, "input-ftp-proxy", &ret_ftp_proxy, - &ftpfs_proxy_host_id), + QUICK_INPUT (ftpfs_proxy_host, "input-ftp-proxy", &ret_ftp_proxy, + &ftpfs_proxy_host_id, FALSE, FALSE, INPUT_COMPLETE_HOSTNAMES), QUICK_CHECKBOX (N_("&Use ~/.netrc"), &ftpfs_use_netrc, NULL), QUICK_CHECKBOX (N_("Use &passive mode"), &ftpfs_use_passive_connections, NULL), QUICK_CHECKBOX (N_("Use passive mode over pro&xy"), @@ -1042,7 +1046,8 @@ cd_dialog (void) char *my_str; quick_widget_t quick_widgets[] = { - QUICK_LABELED_INPUT (N_("cd"), input_label_left, "", 2, "input", &my_str, NULL), + QUICK_LABELED_INPUT (N_("cd"), input_label_left, "", "input", &my_str, NULL, FALSE, TRUE, + INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_CD), QUICK_END }; @@ -1072,10 +1077,10 @@ symlink_dialog (const vfs_path_t * existing_vpath, const vfs_path_t * new_vpath, /* *INDENT-OFF* */ QUICK_LABELED_INPUT (N_("Existing filename (filename symlink will point to):"), input_label_above, - existing, 0, "input-2", ret_existing, NULL), + existing, "input-2", ret_existing, NULL, FALSE, FALSE, INPUT_COMPLETE_FILENAMES), QUICK_SEPARATOR (FALSE), QUICK_LABELED_INPUT (N_("Symbolic link filename:"), input_label_above, - new, 0, "input-1", ret_new, NULL), + new, "input-1", ret_new, NULL, FALSE, FALSE, INPUT_COMPLETE_FILENAMES), QUICK_BUTTONS_OK_CANCEL, QUICK_END /* *INDENT-ON* */ @@ -1198,11 +1203,11 @@ vfs_smb_get_authinfo (const char *host, const char *share, const char *domain, c QUICK_SEPARATOR (FALSE), QUICK_LABEL (N_("Password:"), NULL), QUICK_NEXT_COLUMN, - QUICK_INPUT (domain, 0, "auth_domain", &ret_domain, NULL), + QUICK_INPUT (domain, "auth_domain", &ret_domain, NULL, FALSE, FALSE, INPUT_COMPLETE_HOSTNAMES), QUICK_SEPARATOR (FALSE), - QUICK_INPUT (user, 0, "auth_name", &ret_user, NULL), + QUICK_INPUT (user, "auth_name", &ret_user, NULL, FALSE, FALSE, INPUT_COMPLETE_USERNAMES), QUICK_SEPARATOR (FALSE), - QUICK_INPUT ("", 1, "auth_password", &ret_password, NULL), + QUICK_INPUT ("", "auth_password", &ret_password, NULL, TRUE, FALSE, INPUT_COMPLETE_NONE), QUICK_STOP_COLUMNS, QUICK_BUTTONS_OK_CANCEL, QUICK_END diff --git a/src/filemanager/cmd.c b/src/filemanager/cmd.c index 39cb9a22f..d50411732 100644 --- a/src/filemanager/cmd.c +++ b/src/filemanager/cmd.c @@ -197,7 +197,8 @@ set_panel_filter (WPanel * p) reg_exp = input_dialog_help (_("Filter"), _("Set expression for filtering filenames"), - "[Filter...]", MC_HISTORY_FM_PANEL_FILTER, x, FALSE); + "[Filter...]", MC_HISTORY_FM_PANEL_FILTER, x, FALSE, + INPUT_COMPLETE_FILENAMES); if (!reg_exp) return; set_panel_filter_to (p, reg_exp); @@ -218,7 +219,8 @@ select_unselect_cmd (const char *title, const char *history_name, gboolean do_se quick_widget_t quick_widgets[] = { /* *INDENT-OFF* */ - QUICK_INPUT (INPUT_LAST_TEXT, 0, history_name, ®_exp, NULL), + QUICK_INPUT (INPUT_LAST_TEXT, history_name, ®_exp, NULL, + FALSE, FALSE, INPUT_COMPLETE_FILENAMES), QUICK_START_COLUMNS, QUICK_CHECKBOX (N_("&Files only"), &files_only, NULL), QUICK_CHECKBOX (N_("&Using shell patterns"), &shell_patterns, NULL), @@ -424,7 +426,8 @@ do_link (link_type_t link_type, const char *fname) if (link_type == LINK_HARDLINK) { src = g_strdup_printf (_("Link %s to:"), str_trunc (fname, 46)); - dest = input_expand_dialog (_("Link"), src, MC_HISTORY_FM_LINK, ""); + dest = + input_expand_dialog (_("Link"), src, MC_HISTORY_FM_LINK, "", INPUT_COMPLETE_FILENAMES); if (!dest || !*dest) goto cleanup; save_cwds_stat (); @@ -494,7 +497,10 @@ nice_cd (const char *text, const char *xtext, const char *help, if (!SELECTED_IS_PANEL) return; - machine = input_dialog_help (text, xtext, help, history_name, "", strip_password); + machine = + input_dialog_help (text, xtext, help, history_name, "", strip_password, + INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_CD | INPUT_COMPLETE_HOSTNAMES | + INPUT_COMPLETE_USERNAMES); if (machine == NULL) return; @@ -706,7 +712,8 @@ view_file_cmd (void) filename = input_expand_dialog (_("View file"), _("Filename:"), - MC_HISTORY_FM_VIEW_FILE, selection (current_panel)->fname); + MC_HISTORY_FM_VIEW_FILE, selection (current_panel)->fname, + INPUT_COMPLETE_FILENAMES); if (!filename) return; @@ -740,7 +747,8 @@ view_filtered_cmd (void) command = input_dialog (_("Filtered view"), _("Filter command and arguments:"), - MC_HISTORY_FM_FILTERED_VIEW, initial_command); + MC_HISTORY_FM_FILTERED_VIEW, initial_command, + INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_COMMANDS); if (command != NULL) { @@ -825,7 +833,7 @@ edit_cmd_new (void) char *fname; fname = input_expand_dialog (_("Edit file"), _("Enter file name:"), - MC_HISTORY_EDIT_LOAD, ""); + MC_HISTORY_EDIT_LOAD, "", INPUT_COMPLETE_FILENAMES); if (fname == NULL) return; @@ -913,7 +921,8 @@ mkdir_cmd (void) dir = input_expand_dialog (_("Create a new Directory"), - _("Enter directory name:"), MC_HISTORY_FM_MKDIR, name); + _("Enter directory name:"), MC_HISTORY_FM_MKDIR, name, + INPUT_COMPLETE_FILENAMES); if (dir != NULL && dir != '\0') { @@ -1349,7 +1358,9 @@ edit_symlink_cmd (void) if (i > 0) { buffer[i] = 0; - dest = input_expand_dialog (_("Edit symlink"), q, MC_HISTORY_FM_EDIT_LINK, buffer); + dest = + input_expand_dialog (_("Edit symlink"), q, MC_HISTORY_FM_EDIT_LINK, buffer, + INPUT_COMPLETE_FILENAMES); if (dest) { if (*dest && strcmp (buffer, dest)) diff --git a/src/filemanager/command.c b/src/filemanager/command.c index 4cb197319..00d787d9d 100644 --- a/src/filemanager/command.c +++ b/src/filemanager/command.c @@ -476,7 +476,8 @@ command_new (int y, int x, int cols) }; cmd = input_new (y, x, (int *) command_colors, cols, "", "cmdline", - INPUT_COMPLETE_DEFAULT | INPUT_COMPLETE_CD | INPUT_COMPLETE_COMMANDS | + INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_VARIABLES | INPUT_COMPLETE_USERNAMES + | INPUT_COMPLETE_HOSTNAMES | INPUT_COMPLETE_CD | INPUT_COMPLETE_COMMANDS | INPUT_COMPLETE_SHELL_ESC); /* Add our hooks */ diff --git a/src/filemanager/ext.c b/src/filemanager/ext.c index d2978d297..b022dcb79 100644 --- a/src/filemanager/ext.c +++ b/src/filemanager/ext.c @@ -227,7 +227,9 @@ exec_make_shell_string (const char *lc_data, const vfs_path_t * filename_vpath) char *parameter; parameter_found = FALSE; - parameter = input_dialog (_("Parameter"), lc_prompt, MC_HISTORY_EXT_PARAMETER, ""); + parameter = + input_dialog (_("Parameter"), lc_prompt, MC_HISTORY_EXT_PARAMETER, "", + INPUT_COMPLETE_NONE); if (parameter == NULL) { /* User canceled */ diff --git a/src/filemanager/filegui.c b/src/filemanager/filegui.c index b9fcfeb9a..57eff7315 100644 --- a/src/filemanager/filegui.c +++ b/src/filemanager/filegui.c @@ -1180,15 +1180,15 @@ file_mask_dialog (FileOpContext * ctx, FileOperation operation, quick_widget_t quick_widgets[] = { /* *INDENT-OFF* */ QUICK_LABELED_INPUT (fmd_buf, input_label_above, - easy_patterns ? "*" : "^(.*)$", 0, "input-def", &source_mask, - NULL), + easy_patterns ? "*" : "^(.*)$", "input-def", &source_mask, + NULL, FALSE, FALSE, INPUT_COMPLETE_FILENAMES), QUICK_START_COLUMNS, QUICK_SEPARATOR (FALSE), QUICK_NEXT_COLUMN, QUICK_CHECKBOX (N_("&Using shell patterns"), &source_easy_patterns, NULL), QUICK_STOP_COLUMNS, QUICK_LABELED_INPUT (N_("to:"), input_label_above, - def_text_secure, 0, "input2", &dest_dir, NULL), + def_text_secure, "input2", &dest_dir, NULL, FALSE, FALSE, INPUT_COMPLETE_FILENAMES), QUICK_SEPARATOR (TRUE), QUICK_START_COLUMNS, QUICK_CHECKBOX (N_("Follow &links"), &ctx->follow_links, NULL), diff --git a/src/filemanager/find.c b/src/filemanager/find.c index 809129980..7b8b728b3 100644 --- a/src/filemanager/find.c +++ b/src/filemanager/find.c @@ -609,7 +609,7 @@ find_parameters (char **start_dir, ssize_t * start_dir_len, add_widget (find_dlg, label_new (y1++, x1, _("Start at:"))); in_start = input_new (y1, x1, input_get_default_colors (), cols - b0 - 7, in_start_dir, "start", - INPUT_COMPLETE_DEFAULT); + INPUT_COMPLETE_CD | INPUT_COMPLETE_FILENAMES); add_widget (find_dlg, in_start); add_widget (find_dlg, button_new (y1++, cols - b0 - 3, B_TREE, NORMAL_BUTTON, buts[0], NULL)); @@ -621,7 +621,7 @@ find_parameters (char **start_dir, ssize_t * start_dir_len, in_ignore = input_new (y1++, x1, input_get_default_colors (), cols - 6, options.ignore_dirs != NULL ? options.ignore_dirs : "", "ignoredirs", - INPUT_COMPLETE_DEFAULT); + INPUT_COMPLETE_CD | INPUT_COMPLETE_FILENAMES); widget_disable (WIDGET (in_ignore), !options.ignore_dirs_enable); add_widget (find_dlg, in_ignore); @@ -633,7 +633,7 @@ find_parameters (char **start_dir, ssize_t * start_dir_len, add_widget (find_dlg, label_new (y1++, x1, file_name_label)); in_name = input_new (y1++, x1, input_get_default_colors (), cw, INPUT_LAST_TEXT, "name", - INPUT_COMPLETE_DEFAULT); + INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_CD); add_widget (find_dlg, in_name); /* Start 2nd column */ @@ -641,7 +641,7 @@ find_parameters (char **start_dir, ssize_t * start_dir_len, add_widget (find_dlg, content_label); in_with = input_new (y2++, x2, input_get_default_colors (), cw, INPUT_LAST_TEXT, - MC_HISTORY_SHARED_SEARCH, INPUT_COMPLETE_DEFAULT); + MC_HISTORY_SHARED_SEARCH, INPUT_COMPLETE_NONE); in_with->label = content_label; widget_disable (WIDGET (in_with), disable); add_widget (find_dlg, in_with); diff --git a/src/filemanager/hotlist.c b/src/filemanager/hotlist.c index 6139edd9d..dbfd5cc12 100644 --- a/src/filemanager/hotlist.c +++ b/src/filemanager/hotlist.c @@ -960,9 +960,11 @@ add_new_entry_input (const char *header, const char *text1, const char *text2, { quick_widget_t quick_widgets[] = { /* *INDENT-OFF* */ - QUICK_LABELED_INPUT (text1, input_label_above, *r1, 0, "input-lbl", r1, NULL), + QUICK_LABELED_INPUT (text1, input_label_above, *r1, "input-lbl", r1, NULL, + FALSE, FALSE, INPUT_COMPLETE_NONE), QUICK_SEPARATOR (FALSE), - QUICK_LABELED_INPUT (text2, input_label_above, *r2, 0, "input-lbl", r2, NULL), + QUICK_LABELED_INPUT (text2, input_label_above, *r2, "input-lbl", r2, NULL, + FALSE, FALSE, INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_CD), QUICK_START_BUTTONS (TRUE, TRUE), QUICK_BUTTON (N_("&Append"), B_APPEND, NULL, NULL), QUICK_BUTTON (N_("&Insert"), B_INSERT, NULL, NULL), @@ -1023,7 +1025,8 @@ add_new_group_input (const char *header, const char *label, char **result) { quick_widget_t quick_widgets[] = { /* *INDENT-OFF* */ - QUICK_LABELED_INPUT (label, input_label_above, "", 0, "input", result, NULL), + QUICK_LABELED_INPUT (label, input_label_above, "", "input", result, NULL, + FALSE, FALSE, INPUT_COMPLETE_NONE), QUICK_START_BUTTONS (TRUE, TRUE), QUICK_BUTTON (N_("&Append"), B_APPEND, NULL, NULL), QUICK_BUTTON (N_("&Insert"), B_INSERT, NULL, NULL), @@ -1565,7 +1568,9 @@ add2hotlist_cmd (void) l = str_term_width1 (cp); label_string = vfs_path_to_str_flags (current_panel->cwd_vpath, 0, VPF_STRIP_PASSWORD); lc_prompt = g_strdup_printf (cp, str_trunc (label_string, COLS - 2 * UX - (l + 8))); - label = input_dialog (_("Add to hotlist"), lc_prompt, MC_HISTORY_HOTLIST_ADD, label_string); + label = + input_dialog (_("Add to hotlist"), lc_prompt, MC_HISTORY_HOTLIST_ADD, label_string, + INPUT_COMPLETE_NONE); g_free (lc_prompt); if (label == NULL || *label == '\0') diff --git a/src/filemanager/panelize.c b/src/filemanager/panelize.c index 5954b5ea9..5c39a7dc5 100644 --- a/src/filemanager/panelize.c +++ b/src/filemanager/panelize.c @@ -186,9 +186,13 @@ init_panelize (void) add_widget (panelize_dlg, label_new (y++, UX, _("Command"))); pname = input_new (y++, UX, input_get_default_colors (), panelize_cols - UX * 2, "", "in", - INPUT_COMPLETE_DEFAULT); + INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_HOSTNAMES | INPUT_COMPLETE_COMMANDS | + INPUT_COMPLETE_VARIABLES | INPUT_COMPLETE_USERNAMES | INPUT_COMPLETE_CD | + INPUT_COMPLETE_SHELL_ESC); add_widget (panelize_dlg, pname); + + add_widget (panelize_dlg, hline_new (y++, -1, -1)); x = (panelize_cols - blen) / 2; @@ -258,7 +262,8 @@ add2panelize_cmd (void) if (pname->buffer && (*pname->buffer)) { label = input_dialog (_("Add to external panelize"), - _("Enter command label:"), MC_HISTORY_FM_PANELIZE_ADD, ""); + _("Enter command label:"), MC_HISTORY_FM_PANELIZE_ADD, "", + INPUT_COMPLETE_NONE); if (!label) return; if (!*label) diff --git a/src/filemanager/tree.c b/src/filemanager/tree.c index b2a698558..628e12070 100644 --- a/src/filemanager/tree.c +++ b/src/filemanager/tree.c @@ -785,7 +785,8 @@ tree_copy (WTree * tree, const char *default_dest) g_snprintf (msg, sizeof (msg), _("Copy \"%s\" directory to:"), str_trunc (selected_ptr_name, 50)); dest = input_expand_dialog (Q_ ("DialogTitle|Copy"), - msg, MC_HISTORY_FM_TREE_COPY, default_dest); + msg, MC_HISTORY_FM_TREE_COPY, default_dest, + INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_CD); if (dest != NULL && *dest != '\0') { @@ -824,7 +825,8 @@ tree_move (WTree * tree, const char *default_dest) g_snprintf (msg, sizeof (msg), _("Move \"%s\" directory to:"), str_trunc (selected_ptr_name, 50)); dest = - input_expand_dialog (Q_ ("DialogTitle|Move"), msg, MC_HISTORY_FM_TREE_MOVE, default_dest); + input_expand_dialog (Q_ ("DialogTitle|Move"), msg, MC_HISTORY_FM_TREE_MOVE, default_dest, + INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_CD); if (dest == NULL || *dest == '\0') goto ret; diff --git a/src/filemanager/usermenu.c b/src/filemanager/usermenu.c index a60ec95d8..ea8ede44e 100644 --- a/src/filemanager/usermenu.c +++ b/src/filemanager/usermenu.c @@ -474,7 +474,10 @@ execute_menu_command (WEdit * edit_widget, const char *commands, gboolean show_p char *tmp; *parameter = 0; parameter = - input_dialog (_("Parameter"), lc_prompt, MC_HISTORY_FM_MENU_EXEC_PARAM, ""); + input_dialog (_("Parameter"), lc_prompt, MC_HISTORY_FM_MENU_EXEC_PARAM, "", + INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_CD | + INPUT_COMPLETE_HOSTNAMES | INPUT_COMPLETE_VARIABLES | + INPUT_COMPLETE_USERNAMES); if (!parameter || !*parameter) { /* User canceled */ diff --git a/src/vfs/ftpfs/ftpfs.c b/src/vfs/ftpfs/ftpfs.c index 39fef39f8..c16b3e1d7 100644 --- a/src/vfs/ftpfs/ftpfs.c +++ b/src/vfs/ftpfs/ftpfs.c @@ -654,7 +654,8 @@ ftpfs_login_server (struct vfs_class *me, struct vfs_s_super *super, const char p = g_strdup_printf (_("FTP: Account required for user %s"), super->path_element->user); - op = input_dialog (p, _("Account:"), MC_HISTORY_FTPFS_ACCOUNT, ""); + op = input_dialog (p, _("Account:"), MC_HISTORY_FTPFS_ACCOUNT, "", + INPUT_COMPLETE_USERNAMES); g_free (p); if (op == NULL) ERRNOR (EPERM, 0); diff --git a/src/viewer/dialogs.c b/src/viewer/dialogs.c index 7a251bb49..8fba696d2 100644 --- a/src/viewer/dialogs.c +++ b/src/viewer/dialogs.c @@ -88,7 +88,8 @@ mcview_dialog_search (mcview_t * view) quick_widget_t quick_widgets[] = { /* *INDENT-OFF* */ QUICK_LABELED_INPUT (N_("Enter search string:"), input_label_above, - INPUT_LAST_TEXT, 0, MC_HISTORY_SHARED_SEARCH, &exp, NULL), + INPUT_LAST_TEXT, MC_HISTORY_SHARED_SEARCH, &exp, + NULL, FALSE, FALSE, INPUT_COMPLETE_NONE), QUICK_SEPARATOR (TRUE), QUICK_START_COLUMNS, QUICK_RADIO (num_of_types, (const char **) list_of_types, @@ -197,7 +198,8 @@ mcview_dialog_goto (mcview_t * view, off_t * offset) { quick_widget_t quick_widgets[] = { /* *INDENT-OFF* */ - QUICK_INPUT (INPUT_LAST_TEXT, 0, MC_HISTORY_VIEW_GOTO, &exp, NULL), + QUICK_INPUT (INPUT_LAST_TEXT, MC_HISTORY_VIEW_GOTO, &exp, NULL, + FALSE, FALSE, INPUT_COMPLETE_NONE), QUICK_RADIO (num_of_types, (const char **) mc_view_goto_str, (int *) ¤t_goto_type, NULL), QUICK_BUTTONS_OK_CANCEL, diff --git a/tests/lib/Makefile.am b/tests/lib/Makefile.am index 8dd721a3b..f5ed3a3d8 100644 --- a/tests/lib/Makefile.am +++ b/tests/lib/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = . mcconfig search vfs +SUBDIRS = . mcconfig search vfs widget AM_CPPFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir) @CHECK_CFLAGS@ diff --git a/tests/lib/widget/Makefile.am b/tests/lib/widget/Makefile.am new file mode 100644 index 000000000..37a91efab --- /dev/null +++ b/tests/lib/widget/Makefile.am @@ -0,0 +1,19 @@ + +AM_CPPFLAGS = \ + $(GLIB_CFLAGS) \ + -I$(top_srcdir) \ + -I$(top_srcdir)/lib/vfs \ + @CHECK_CFLAGS@ + +AM_LDFLAGS = @TESTS_LDFLAGS@ + +LIBS=@CHECK_LIBS@ \ + $(top_builddir)/lib/libmc.la + +TESTS = \ + complete_engine + +check_PROGRAMS = $(TESTS) + +complete_engine_SOURCES = \ + complete_engine.c diff --git a/tests/lib/widget/complete_engine.c b/tests/lib/widget/complete_engine.c new file mode 100644 index 000000000..94352b217 --- /dev/null +++ b/tests/lib/widget/complete_engine.c @@ -0,0 +1,254 @@ +/* + lib/widget - tests for autocomplete feature + + Copyright (C) 2013 + The Free Software Foundation, Inc. + + Written by: + Slava Zanko , 2013 + + This file is part of the Midnight Commander. + + The Midnight Commander is free software: you can redistribute it + and/or modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. + + The Midnight Commander 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#define TEST_SUITE_NAME "/lib/widget" + +#include + +#include + +#include "lib/global.h" +#include "lib/strutil.h" +#include "lib/widget.h" + +/* --------------------------------------------------------------------------------------------- */ + +void complete_engine_fill_completions (WInput * in); +char **try_complete (char *text, int *lc_start, int *lc_end, input_complete_t flags); + +/* --------------------------------------------------------------------------------------------- */ + +/* @CapturedValue */ +static char *try_complete__text__captured; +/* @CapturedValue */ +static int try_complete__lc_start__captured; +/* @CapturedValue */ +static int try_complete__lc_end__captured; +/* @CapturedValue */ +static input_complete_t try_complete__flags__captured; + +/* @ThenReturnValue */ +static char **try_complete__return_value; + +/* @Mock */ +char ** +try_complete (char *text, int *lc_start, int *lc_end, input_complete_t flags) +{ + try_complete__text__captured = g_strdup (text); + try_complete__lc_start__captured = *lc_start; + try_complete__lc_end__captured = *lc_end; + try_complete__flags__captured = flags; + + return try_complete__return_value; +} + +static void +try_complete__init (void) +{ + try_complete__text__captured = NULL; + try_complete__lc_start__captured = 0; + try_complete__lc_end__captured = 0; + try_complete__flags__captured = 0; +} + +static void +try_complete__deinit (void) +{ + g_free (try_complete__text__captured); +} + +/* --------------------------------------------------------------------------------------------- */ + +/* @Before */ +static void +setup (void) +{ + str_init_strings (NULL); + try_complete__init (); +} + +/* --------------------------------------------------------------------------------------------- */ + +/* @After */ +static void +teardown (void) +{ + try_complete__deinit (); + str_uninit_strings (); +} + +/* --------------------------------------------------------------------------------------------- */ + +/* @DataSource("test_complete_engine_fill_completions_ds") */ +/* *INDENT-OFF* */ +static const struct test_complete_engine_fill_completions_ds +{ + const char *input_buffer; + const int input_point; + const input_complete_t input_completion_flags; + int expected_start; + int expected_end; +} test_complete_engine_fill_completions_ds[] = +{ + { + "string", + 3, + INPUT_COMPLETE_NONE, + 0, + 3 + }, + { + "some string", + 7, + INPUT_COMPLETE_NONE, + 0, + 7 + }, + { + "some string", + 7, + INPUT_COMPLETE_SHELL_ESC, + 5, + 7 + }, + { + "some\\ string111", + 9, + INPUT_COMPLETE_SHELL_ESC, + 0, + 9 + }, + { + "some\\\tstring111", + 9, + INPUT_COMPLETE_SHELL_ESC, + 0, + 9 + }, + { + "some\tstring", + 7, + INPUT_COMPLETE_NONE, + 5, + 7 + }, + { + "some;string", + 7, + INPUT_COMPLETE_NONE, + 5, + 7 + }, + { + "some|string", + 7, + INPUT_COMPLETE_NONE, + 5, + 7 + }, + { + "somestring", + 7, + INPUT_COMPLETE_NONE, + 5, + 7 + }, + { + "some!@#$%^&*()_\\+~`\"',./?:string", + 30, + INPUT_COMPLETE_NONE, + 0, + 30 + }, +}; +/* *INDENT-ON* */ +// " \t;|<>" + +/* @Test(dataSource = "test_complete_engine_fill_completions_ds") */ +/* *INDENT-OFF* */ +START_TEST (test_complete_engine_fill_completions) +/* *INDENT-ON* */ +{ + /* given */ + + WInput *w_input; + const struct test_complete_engine_fill_completions_ds *data = + &test_complete_engine_fill_completions_ds[_i]; + + w_input = g_new (WInput, 1); + w_input->buffer = g_strdup (data->input_buffer); + w_input->point = data->input_point; + w_input->completion_flags = data->input_completion_flags; + + /* when */ + complete_engine_fill_completions (w_input); + + /* then */ + g_assert_cmpstr (try_complete__text__captured, ==, data->input_buffer); + ck_assert_int_eq (try_complete__lc_start__captured, data->expected_start); + ck_assert_int_eq (try_complete__lc_end__captured, data->expected_end); + ck_assert_int_eq (try_complete__flags__captured, data->input_completion_flags); + +} +/* *INDENT-OFF* */ +END_TEST +/* *INDENT-ON* */ + +/* --------------------------------------------------------------------------------------------- */ + +int +main (void) +{ + int number_failed; + + Suite *s = suite_create (TEST_SUITE_NAME); + TCase *tc_core = tcase_create ("Core"); + SRunner *sr; + + tcase_add_checked_fixture (tc_core, setup, teardown); + + /* Add new tests here: *************** */ + tcase_add_loop_test (tc_core, test_complete_engine_fill_completions, 0, + sizeof (test_complete_engine_fill_completions_ds) / + sizeof (test_complete_engine_fill_completions_ds[0])); + /* *********************************** */ + + suite_add_tcase (s, tc_core); + sr = srunner_create (s); + srunner_set_log (sr, "complete_engine.log"); + srunner_run_all (sr, CK_NORMAL); + number_failed = srunner_ntests_failed (sr); + srunner_free (sr); + return (number_failed == 0) ? 0 : 1; +} + +/* --------------------------------------------------------------------------------------------- */