GNU readline

2008 年 4 月 26 日 | カテゴリー: プログラム

2008042601.png

The GNU Readline Library

GNU readline は文字列入力用ライブラリです。
このライブラリを使って入力を行うと、bash のように、↑キーを押すと履歴の参照が可能だったり、タブキーで入力文字列の補完が可能だったりします。

使うこと自体は初めてではありませんが、今回まじめに使ってみたので(readline/history.h の構造体や関数を確認し、履歴を利用するアプリケーションを作っていた)、そのまとめです。

GNU readline を使うには

/usr/include/readline/readline.h
/usr/include/readline/history.h

BSD や Linux ディストリビューションで提供されているパッケージなどからインストールが可能です。
上記ヘッダーファイルを使います。

文字列入力

char *readline(const char *prompt);

引数に入れた文字列を入力時のプロンプト文字列として、文字列入力を行います。
readline が入力された文字列分のメモリ領域を確保し、先頭ポインタを返してくれます。
メモリ領域の開放は自分で行う必要があります。

履歴への登録

void add_history(const char *line);

指定した文字列を履歴へ登録します。
readline から入力した文字列しか登録できないというわけではなく、好きな文字列を登録することが可能です。

履歴の読み出し、書き出し

int read_history(const char *filename)

指定した履歴ファイルを読み出します。
成功すると 0 を返します。

int write_history(const char *filename)

指定したファイルに履歴を書き出します。
成功すると 0 を返します。

履歴の参照

typedef struct _hist_entry {
  char *line;
  char *timestamp;
  histdata_t data;
} HIST_ENTRY;

履歴はこのような構造体に保存されています。

HIST_ENTRY *current_history(void)

現在の行を返します。

HIST_ENTRY *previous_history(void)

1つ前の行を返します。

HIST_ENTRY **history_list(void)

HIST_ENTRY の配列を返します。

他に使える関数

/usr/include/readline/history.h を参照することで使い方を知ることができます。

サンプルコード

HelloReadline.c

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

int main(int argc, char *argv[]) {

    /* ループに使うインデックスです。 */
    int i = 0;
    /* 入力された文字列の参照に使います。 */
    char *str = NULL;
    /* 履歴リストの参照に使います。 */
    HIST_ENTRY **historyList = NULL;

    /* 文字列入力プロンプトを表示します。 */
    while(NULL != (str = readline("input "))) {
        /* 何も入力されなかった場合は無視します。メモリの解放を忘れないでください。 */
        if(*str == '\0') {
            free(str);
            continue;
        }
        /* quit が入力されたらループを抜けます。文字列比較には strcmp を使用します。 */
        if(strcmp(str, "quit") == 0) {
            free(str);
            break;
        }
        /* 入力された文字列を履歴へ登録します。 */
        add_history(str);
        /* 入力された文字列をそのまま出力します。 */
        printf("output: %s\n", str);
        free(str);
    }

    printf('-- History List --\n');

    /* 履歴リストを取得します。 */
    historyList = history_list();

    /* 履歴を1行ずつ参照します。 */
    while(historyList[i] != NULL) {
        /* 履歴を1行取得します。 */
        HIST_ENTRY *history = historyList[i];
        /* 履歴に含まれる文字列を出力します。 */
        printf("%s\n", history->line);
        /* インデックスを次に進めます。 */
        i++;
    }

    /* 履歴リストをファイルに書き出します。 */
    write_history("history.txt");

    /* プログラムを終了します。 */
    return EXIT_SUCCESS;
}

1. quit が入力されるまで、入力された文字列をそのまま出力する。
2. quit が入力されたら、それまでに入力された履歴リストを出力する。
3. 履歴リストをファイルに出力する。

コンパイル

gcc -o HelloReadline -Wall -lreadline -lcurses HelloReadline.c

リンカオプションが必要です。

コメントはまだありません。