/* Completion, from vi's point of view. */ int rl_vi_complete (int ignore, int key) { if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point]))) { if (!whitespace (rl_line_buffer[rl_point + 1])) rl_vi_end_word (1, 'E'); rl_point++; } if (key == '*') rl_complete_internal ('*'); /* Expansion and replacement. */ else if (key == '=') rl_complete_internal ('?'); /* List possible completions. */ else if (key == '\\') rl_complete_internal (TAB); /* Standard Readline completion. */ else rl_complete (0, key); if (key == '*' || key == '\\') { _rl_vi_set_last (key, 1, rl_arg_sign); rl_vi_insertion_mode (ignore, key); } return (0); }
static int tab_callback(int count, int key) { if (!rl_point) { strip_initial_spaces += tab_width; return 0; } int i; for (i = line_start(rl_point); i < rl_point; i++) { if (rl_line_buffer[i] != ' ') { // do tab completion i = rl_point; rl_complete_internal('!'); if (i < rl_point && rl_line_buffer[rl_point-1] == ' ') { rl_delete_text(rl_point-1, rl_point); rl_point = rl_point-1; } return 0; } } // indent to next tab stop if (suppress_space()) { spaces_suppressed += tab_width; } else { i = line_start(rl_point) + prompt_length; do { rl_insert_text(" "); } while ((rl_point - i) % tab_width); } return 0; }
int complete_filenames() { if (!complete_filenames_query()) return 0; char * bk_completer_word_break_characters = rl_completer_word_break_characters; char * (*bk_completion_entry_function)(const char*, int) = rl_completion_entry_function; rl_completer_word_break_characters = " \t\n\"\\'`@$><=;|&{("; rl_completion_entry_function = rl_filename_completion_function; rl_complete_internal('!'); rl_completer_word_break_characters = bk_completer_word_break_characters; rl_completion_entry_function = bk_completion_entry_function; return 1; }
int rline_rl_complete (struct rline *rline, struct tgdb_list *list, display_callback display_cb) { int size; int key; rl_command_func_t *compare_func = NULL; if (!rline) return -1; /* Currently, if readline output's the tab completion to rl_outstream, it will fill * the pty between it and CGDB and will cause CGDB to hang. */ if (!display_cb) return -1; size = tgdb_list_size (list); if (size == 0) { rl_completion_word_break_hook = NULL; rl_completion_entry_function = NULL; } else { rl_completion_word_break_hook = rline_rl_cpvfunc_t; rl_completion_entry_function = rline_rl_completion_entry_function; } rl_completion_display_matches_hook = display_cb; rline_local_iter = tgdb_list_get_first (list); /* This is probably a hack, however it works for now. * * Basically, rl_complete is working fine. After the call to rl_complete, * rl_line_buffer contains the proper data. However, the CGDB main loop * always call rline_rl_forced_update_display, which in the case of tab * completion does this, (gdb) b ma(gdb) b main * * Normally, this works fine because the user hits '\n', which puts the prompt * on the next line. In this case, the user hit's \t. * * In order work around this problem, simply putting the \r should work * for now. * * This obviously shouldn't be done when readline is doing * `?' means list the possible completions. * style completion. Because that actuall does list all of the values on * a different line. In this situation the \r goes after the completion * is done, since only the current prompt is on that line. */ /* Another confusing comparison. This checks to see if the last * readline function and the current readline function and the * tab completion callback are all the same. This ensures that this * is the second time the user hit \t in a row. Instead of simply * calling rl_complete_internal, it's better to call, rl_completion_mode * because this checks to see what kind of completion should be done. */ if (rline->rline_rl_last_func == rline->tab_completion && rline->rline_rl_last_func == rl_last_func) compare_func = rline->tab_completion; key = rl_completion_mode (compare_func); if (key == TAB) fprintf (rline->output, "\r"); rl_complete_internal (key); if (key != TAB) fprintf (rline->output, "\r"); return 0; }