使用 Readline 按 Tab 键时禁止打印新提示 [英] Suppress printing a new prompt when pressing tab with Readline

查看:68
本文介绍了使用 Readline 按 Tab 键时禁止打印新提示的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 C 语言的 Readline 库中使用自动补全时,两次输入 tab 键时会重新打印提示:

When using the auto completion with the Readline library in C, the prompt is reprinted when typing the tab key twice:

(prompt) view NAME_OF_F (user presses tab twice)
NAME_OF_FILE1   NAME_OF_FILE2   (suggestions by Readline)
(prompt) view NAME_OF_F 

我想通过保留第一行下面的建议来抑制第三行提示的重印:

I'd like to suppress the reprinting of the prompt on the 3rd line by keeping the first line printed with the suggestions below it like such:

(prompt) view NAME_OF_F (user presses tab twice)
NAME_OF_FILE1   NAME_OF_FILE2   (suggestions by Readline)

我希望光标回到有提示的第一行的末尾.

I'd like the cursor back at the end of the first line that has the prompt.

使用 gcc -Wall -O0 -ggdb -fno-builtin rline.c -o rline -lreadline -ltermcap 编译.

这是一个代码示例:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <readline/readline.h>

int execute_line(char *line);
void initialize_readline();
static char **fileman_completion(char *text, int start, int end);
static char *command_generator(char *text, int state);

char *command[] = { "view", "quit", (char *)NULL };

int done; /* When non-zero, this global means the user is done using this program. */

int main(int argc, char **argv)
{
    char *line;
    initialize_readline();  /* Bind our completer. */
    for ( ; done == 0; ) {
        line = readline("> ");

        if (!line) 
            break;

        if (*line) 
            execute_line(line);
        free(line);
    }
    return 0;
}

/* String to pass to system().  This is for the VIEW command. */
static char syscom[1024];

int execute_line(char *line)
{
    int i = 0;
    char *word;
    /* Isolate the command word. */
    while (line[i] && whitespace(line[i]))
        i++;
    word = line + i;

    while (line[i] && !whitespace(line[i])) i++;

    if (line[i]) line[i++] = '\0';

    if (strcmp(word, "quit") == 0) {
        done = 1;
        return 0;
    } else if (strcmp(word, "view")) {
        fprintf(stderr, "%s: Choose only \"view FILE\" or \"quit\" as your command.\n", word);
        return -1;
    }

    /* Get argument to command, if any. */
    while (whitespace(line[i])) i++;

    word = line + i;
    if(!word || !*word) {
        fprintf(stderr, "view: Argument required.\n");
        return -1;
    }
    sprintf(syscom, "more %s", word);
    return system(syscom);
}

void initialize_readline()
{
    rl_readline_name = "rline";
    rl_attempted_completion_function = (rl_completion_func_t *)fileman_completion;
}

static char **fileman_completion(char *text, int start, int end)
{
    if (start == 0)
        return rl_completion_matches(text, (rl_compentry_func_t *)*command_generator);
    return NULL;
}

static char *command_generator(char *text, int state)
{
    static int list_index, len;
    char *name;
    if (!state) {
        list_index = 0;
        len = strlen(text);
    }
    while ((name = command[list_index++]))
        if (strncmp(name, text, len) == 0)
            return strdup(name);
    return NULL;
}

程序只接受命令view FILE_NAME查看文件内容和quit退出程序.该示例是此处的示例程序的简化版本.

The program only accepts the commands view FILE_NAME to view the contents of a file and quit to exit the program. The example is a shortened version of a sample program found here.

推荐答案

感谢 @rici 的启发.我通过一些修改让它与他的功能一起工作.为了使其正常工作,您需要下载 readline 库.在 readline 的 rlprivate.h 文件中,我删除了行 char **lines; 和行 #include "realdine.h" 来自 display.c.然后在您自己的 .c 中,您必须有一个 #include </PATH/TO/display.c>.在该 display.c 中,#include 指向修改后的 rlprivate.h.所有这些都是为了我可以访问 _rl_move_vert(1).

Thanks @rici for the inspiration. I got it working with his function with some modifications. In order for this to work properly you need to download the readline library. In the rlprivate.h file from readline, I removed the lines char **lines;, and the line #include "realdine.h" from display.c. Then in your own .c you must have an #include </PATH/TO/display.c>. In that display.c, an #include points to the modified rlprivate.h. All of this so that I can have access to _rl_move_vert(1).

static void display_matches(char** matches, int len, int max)
{
    int saved_point = rl_point;
    char *saved_line = rl_copy_text(0, rl_end);
    rl_save_prompt();
    rl_replace_line("", 0); // Clear the previous text
    putp(cursor_up);
    _rl_move_vert(1);
    rl_display_match_list(matches, len, max);
    putp(cursor_up);
    rl_restore_prompt();
    rl_replace_line(saved_line, 0);
    rl_point = saved_point;
    rl_redisplay();
    putp(cursor_down);
    free(saved_line);
}

这篇关于使用 Readline 按 Tab 键时禁止打印新提示的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆