[C++] 291 FLTK : ChatGPTアプリの製作 その20 grepによるjson内文字列検索

[M1 Mac, Monterey 12.6.3, clang 13.0.0, FLTK 1.3.8, ChatGPT Plus, NO IDE]

ChatGPT APIとのやりとりを過去ログとしてjsonファイル保管しています。

質問がなるべくダブらないよう、grepコマンドで事前にjsonファイルを検索できるようにしました。

動画ではまず”FLTK”で調べて21ファイルがヒットしたので”Java”でand検索し、1ファイルに絞り込んでいます。

grepFiles関数はChatGPTに書かせようとしたのですが、どう説明してもor検索のコードしか作れないので、こちらでand検索に書き換えました。とは言えdirent構造体を使ってくるあたりは中級以上のエキスパートかと思うほどの熟練度です。

次はJSONの内容をGUI右側に、質問と回答を左側に表示するようにします。

void searchCB(Fl_Widget*, void*){
    // 初期化
    hitShow -> value();
    window -> redraw();

    const char* grepStr = grepInput -> value();
    cout << "grepStr: " << grepStr << endl;

    stringstream iss(grepStr);
    vector<string> words;
    string word;
    while (getline(iss, word, ' ')) {
        words.push_back(word);
    }
    for (const auto& w : words) {
        cout << "word: " << w << endl;
    }

    string dirPath = "/ChatGPT";
    vector<string> paths = grepFiles(words, dirPath);
    for (const auto& p : paths) {
        cout << "path: " << p << endl;
    }

    int pathsNum = paths.size();
    cout << "HITファイル数: " << pathsNum << endl;

    string pathsNumStr;
    if (pathsNum < 10){
        pathsNumStr = to_string(pathsNum) + " / " + to_string(pathsNum);
    } else {
        pathsNumStr = to_string(pathsNum);
    }

    hitShow -> value(pathsNumStr.c_str());
}

vector<string> grepFiles(const vector<string>& words, const string& path) {
    vector<string> result;
    DIR* dir = opendir(path.c_str());

    if (!dir) {
        cerr << "Error: opendir() failed." << endl;
        return result;
    }

    struct dirent* entry;
    while ((entry = readdir(dir)) != nullptr) {
        if (entry->d_type == DT_REG) { // regular file
            string filePath = path + "/" + entry->d_name;
            string command = "grep -l ";

            int count = 0;
            for (const auto& word : words) {
                if (count == 0){
                    command += word + " \"" + filePath + "\"";
                } else {
                    command += "| grep " + word;
                }
                count++;
            }

            // cout << "command:\n" << command << endl;
            
            FILE* pipe = popen(command.c_str(), "r");
            if (!pipe) {
                cerr << "Error: popen() failed." << endl;
                continue;
            }
            char buffer[256];
            if (fgets(buffer, sizeof(buffer), pipe) != nullptr) {
                result.emplace_back(filePath);
            }
            pclose(pipe);
        }
    }
    closedir(dir);
    return result;
}