簡體   English   中英

為什么帶有自定義功能的rl_bind_key在OSX / macOS的讀取行中失敗

[英]Why does rl_bind_key with custom function fail in readline on OSX/macOS

我構建了一個外殼,嘗試使用rl_bind_key()使tab( \\t )鍵做一些自定義操作,但在macOS Sierra中不起作用,但在Ubuntu,Fedora和CentOS上有效。 這是mcve:

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

static int cmd_complete(int count, int key)
{
        printf("\nCustom tab action goes here...\n");
        rl_forced_update_display();
        return 0;
}

char *interactive_input()
{
        char *buffer = readline(" > ");
        return buffer;
}

int main(int argc, char **argv)
{
        rl_bind_key('\t', cmd_complete); // this doesn't seem to work in macOS
        char *buffer = 0;
        while (!buffer || strncmp(buffer, "exit", 4)) {
                if (buffer) { free(buffer); buffer=0; }
                // get command
                buffer = interactive_input();
                printf("awesome command: %s\n", buffer);
        }
        free(buffer);
        return 0;
}

我像這樣使用Clang進行編譯:

$ cc -lreadline cli.c -o cli

造成這種現象的原因是什么,我該如何解決?

我使用的是-lreadline標志,但是我不知道,Clang似乎在秘密使用libedit(我也看到過它也稱為editline)。 在libedit中,由於某種原因(這會帶來另一個問題), rl_bind_key似乎不適用於rl_insert以外的任何東西。

因此,我找到的一種解決方案是使用Homebrew安裝GNU Readline( brew install readline ),然后確保使用該版本,因此進行編譯:

$ cc -lreadline cli.c -o cli -L/usr/local/opt/readline/lib -I/usr/local/opt/readline/include

實際上,當您安裝readline時,它將在安裝結束時告訴您此信息,或者您是否進行brew info readline

gns-mac1:~ gns$ brew info readline
readline: stable 7.0.3 (bottled) [keg-only]
Library for command-line editing
https://tiswww.case.edu/php/chet/readline/rltop.html
/usr/local/Cellar/readline/7.0.3_1 (46 files, 1.5MB)
  Poured from bottle on 2017-10-24 at 12:21:35
From: https://github.com/Homebrew/homebrew-core/blob/master/Formula/readline.rb
==> Caveats
This formula is keg-only, which means it was not symlinked into /usr/local,
because macOS provides the BSD libedit library, which shadows libreadline.
In order to prevent conflicts when programs look for libreadline we are
defaulting this GNU Readline installation to keg-only..

For compilers to find this software you may need to set:
    LDFLAGS:  -L/usr/local/opt/readline/lib
    CPPFLAGS: -I/usr/local/opt/readline/include

libedit rl_bind_key的來源

所以這就是為什么它在libedit中不起作用的原因。 我下載了源代碼,這是rl_bind_key函數的定義方式:

/*
 * bind key c to readline-type function func
 */
int
rl_bind_key(int c, rl_command_func_t *func)
{
    int retval = -1;

    if (h == NULL || e == NULL)
        rl_initialize();

    if (func == rl_insert) {
        /* XXX notice there is no range checking of ``c'' */
        e->el_map.key[c] = ED_INSERT;
        retval = 0;
    }
    return retval;
}

因此,似乎設計為除rl_insert之外rl_insert不能使用。 這似乎是一個錯誤,而不是功能。 我希望我知道如何成為libedit的貢獻者。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM