ujjwall-R / Dree

One single package for visualization, debugging, and exploration of folder hierarchies
70 stars 16 forks source link

Level UP : Directory Navigation using ncurses #62

Closed ujjwall-R closed 7 months ago

ujjwall-R commented 7 months ago

Refer the below code.

#include <iostream>
#include <vector>
#include <string>
#include <ncurses.h>
#include <unistd.h>

struct MenuItem
{
    std::string text;
    std::string path;
};

void renderMenu(const std::vector<MenuItem> &menu, int selected)
{
    clear();
    for (int i = 0; i < menu.size(); ++i)
    {
        if (i == selected)
        {
            attron(A_REVERSE);
        }
        mvprintw(i + 1, 1, menu[i].text.c_str());
        attroff(A_REVERSE);
    }
    refresh();
}

int main()
{
    // Initialize ncurses
    initscr();
    cbreak();
    noecho();
    keypad(stdscr, TRUE);

    // Define menu items
    std::vector<MenuItem> menu = {
        {"Item 1", "/path1"},
        {"Item 2", "/path2"},
        {"Item 3", "/path3"},
        // Add more items as needed
    };

    int currentSelection = 0;
    int key;

    do
    {
        renderMenu(menu, currentSelection);

        key = getch();
        switch (key)
        {
        case KEY_UP:
            currentSelection = std::max(0, currentSelection - 1);
            break;
        case KEY_DOWN:
            currentSelection = std::min(static_cast<int>(menu.size() - 1), currentSelection + 1);
            break;
        case 10: // Enter key
            // Perform action associated with the selected item (change directory and exit)
            if (chdir(menu[currentSelection].path.c_str()) == 0)
            {
                endwin();                      // End ncurses mode before executing new shell
                execlp("zsh", "zsh", nullptr); // Start a new shell in the new directory
                std::cerr << "Error executing new shell." << std::endl;
                return 1;
            }
            else
            {
                std::cerr << "Error changing directory." << std::endl;
            }
            break;
        }
    } while (key != 27); // Exit when the user presses the Esc key

    // Cleanup
    endwin();

    return 0;
}
ujjwall-R commented 7 months ago
#include <ncurses.h>
#include <bits/stdc++.h>

class DreeNode
{
public:
    std::string name;
    std::vector<DreeNode *> children;
    DreeNode(std::string str) { name = str; }
};

class DreeNavigate
{
public:
    void dfs(DreeNode *node, long long depth, long long currentDepth, bool isLastChild, long long mask);
    void navigateTree(DreeNode *root);
    void printTree(DreeNode *root, long long depth);

private:
    long long selectedDepth;
};

void DreeNavigate::dfs(DreeNode *node, long long depth, long long currentDepth, bool isLastChild, long long mask)
{
    for (long long i = 0; i < currentDepth; i++)
    {
        if (((mask >> i) & 1ll) == 0ll)
            addch(ACS_VLINE); // '│'
        else
            printw("     ");
    }

    if (isLastChild)
        addch(ACS_LLCORNER); // '└'
    else
        addch(ACS_LTEE); // '├'

    addch(ACS_HLINE); // '─'
    addch(ACS_HLINE); // '─'

    if (currentDepth == selectedDepth)
        attron(A_STANDOUT); // Highlight the selected depth
    addstr(node->name.c_str());
    if (currentDepth == selectedDepth)
        attroff(A_STANDOUT);

    printw("\n");

    for (size_t i = 0; i < node->children.size(); i++)
    {
        DreeNode *child = node->children[i];
        if (i == node->children.size() - 1)
        {
            mask = mask | (1ll << (currentDepth + 1));
        }
        dfs(child, depth, currentDepth + 1, i == node->children.size() - 1, mask);
    }
}

void DreeNavigate::navigateTree(DreeNode *root)
{
    int ch;
    selectedDepth = 0;
    printTree(root, 3);

    while ((ch = getch()) != 10) // 10 is the ASCII code for Enter key
    {
        switch (ch)
        {
        case KEY_UP:
            selectedDepth = std::max(0ll, selectedDepth - 1);
            break;
        case KEY_DOWN:
            selectedDepth = std::min(3ll, selectedDepth + 1); // Assuming the maximum depth is 3
            break;
        }
        clear();
        printTree(root, 3);
    }
}

void DreeNavigate::printTree(DreeNode *root, long long depth)
{
    dfs(root, depth, 0, true, 0);
    refresh();
}

int main()
{
    // Initialize ncurses
    initscr();

    // Enable special characters (like line-drawing characters)
    keypad(stdscr, TRUE);
    raw();

    // Create an instance of DreeNavigate and call the navigateTree function
    DreeNavigate dreeNavigator;
    DreeNode *root = new DreeNode("root");
    root->name = "Root";
    root->children.push_back(new DreeNode("eg"));
    root->children.push_back(new DreeNode("eg1"));
    root->children[0]->children.push_back(new DreeNode("pg"));
    dreeNavigator.navigateTree(root);

    // Clean up and close ncurses
    endwin();

    return 0;
}