diff --git a/a.out b/a.out index dd386a0..f038771 100755 Binary files a/a.out and b/a.out differ diff --git a/shell.nix b/shell.nix index 3b317dd..bb87a5d 100644 --- a/shell.nix +++ b/shell.nix @@ -4,6 +4,7 @@ pkgs.mkShell { buildInputs = [ pkgs.vivify pkgs.cjson + pkgs.ncurses pkgs.pkg-config ]; } diff --git a/startup.c b/startup.c index 45d39d2..2c5278d 100644 --- a/startup.c +++ b/startup.c @@ -1,8 +1,150 @@ +//gcc startup.c $(pkg-config --cflags --libs libcjson ncurses) #include #include #include #include #include +#include +#include // for PATH_MAX +#include + +char** getVaultsFromDirectory(char *dirString, size_t *count) { + // (TODO LATER) it might be a good idea to check if these directories exist + // (TODO LATER) expand ~ as it does not work with opendir() + // this function is inputed a path to a directory (which comes usually from the config file) and outpus all the suitable directories (so not the hidden ones) which will serve as separate vaults for notes + printf("Opening %s aka the directory of vaults\n", dirString); + + // originally from https://www.geeksforgeeks.org/c/c-program-list-files-sub-directories-directory/ + struct dirent *vaultsDirectoryEntry; + DIR *vaultsDirectory = opendir(dirString); + if (vaultsDirectory == NULL) // opendir returns NULL if couldn't open directory + { + printf("Could not open current directory" ); + exit(1); //something is fucked up + } + char **dirsArray = NULL; // will contain all the dirs/vaults + size_t dirsCount = 0; // we need to count how many dirs there is to always readjust how many memory we alloc + // Refer https://pubs.opengroup.org/onlinepubs/7990989775/xsh/readdir.html + // for readdir() + while ((vaultsDirectoryEntry = readdir(vaultsDirectory)) != NULL) { + printf("%s\n", vaultsDirectoryEntry->d_name); // debugs every file/directory + if (vaultsDirectoryEntry->d_name[0] != '.') { // if the entry don't start with a dot (so hidden dirs and hidden files) + char fullPathEntry[PATH_MAX]; // creates a string of size of the maximum path lenght + snprintf(fullPathEntry, sizeof(fullPathEntry), "%s/%s", dirString, vaultsDirectoryEntry->d_name); // sets the full absolute path to fullPathEntry + + struct stat metadataPathEntry; + if (stat(fullPathEntry, &metadataPathEntry) == 0 && S_ISDIR(metadataPathEntry.st_mode)) { // if this entry is a directory + dirsArray = realloc(dirsArray, (dirsCount + 1)*sizeof(char*)); // resize dirsArray so that + dirsArray[dirsCount] = strdup(vaultsDirectoryEntry->d_name); // copy the dir name into dirsArray + dirsCount++; + } + } + } + // (TODO LATER) Alphabetically sort them + + // free's some used memory + closedir(vaultsDirectory); + *count = dirsCount; + return dirsArray; +} + +char** getNotesFromVault(char *pathToVault, char *vault, int *count) { + // this function is inputed a path to a vault (which was selected before) and outpus all the suitable notes (so not the hidden ones) + printf("Opening %s aka the vault\n", vault); + + // originally from https://www.geeksforgeeks.org/c/c-program-list-files-sub-directories-directory/ + struct dirent *notesDirectoryEntry; + char tempPath[PATH_MAX]; + snprintf(tempPath, sizeof(tempPath), "%s/%s", pathToVault, vault); // sets the full absolute path to fullPathEntry + DIR *vaultDirectory = opendir(tempPath); + if (vaultDirectory == NULL) // opendir returns NULL if couldn't open directory + { + printf("Could not open current directory" ); + exit(1); //something is fucked up + } + char **notesArray = NULL; // will contain all the notes + size_t notesCount = 0; // we need to count how many notes there is to always readjust how many memory we alloc + // Refer https://pubs.opengroup.org/onlinepubs/7990989775/xsh/readdir.html + // for readdir() + while ((notesDirectoryEntry = readdir(vaultDirectory)) != NULL) { + printf("%s\n", notesDirectoryEntry->d_name); // debugs every note + if (notesDirectoryEntry->d_name[0] != '.') { // if the entry don't start with a dot (so hidden dirs and hidden files) + char fullPathEntry[PATH_MAX]; // creates a string of size of the maximum path lenght + snprintf(fullPathEntry, sizeof(fullPathEntry), "%s/%s/%s", pathToVault, vault, notesDirectoryEntry->d_name); // sets the full absolute path to fullPathEntry + + struct stat metadataPathEntry; + if (stat(fullPathEntry, &metadataPathEntry) == 0 && !S_ISDIR(metadataPathEntry.st_mode)) { // if this entry is a file + notesArray = realloc(notesArray, (notesCount + 1)*sizeof(char*)); // resize notesArray so that + notesArray[notesCount] = strdup(notesDirectoryEntry->d_name); // copy the dir name into notesArray + notesCount++; + } + } + } + // (TODO LATER) Alphabetically sort them + // free's some used memory + closedir(vaultDirectory); + *count = notesCount; // passes the number of files + return notesArray; +} + +char* ncursesSelect(char **options, char *optionsType, size_t optionsNumber) { // this fonction make a TUI to select one of multiple options. + int highlight = 0; //curently highlighted option + int choice = 1; //selected index + int key; + + initscr(); //initialize ncurses + cbreak(); // disable line buffering + noecho(); // don't echo key presses + keypad(stdscr, TRUE); // enable arrow keys + while (1) { + clear(); + mvprintw(0,0, "Select %s (Use arrows or WASD, Enter to select):", optionsType); + + // Print options with highlighting + for(int i = 0; i < optionsNumber; i++) { + if (i == highlight) { + attron(A_REVERSE); + } // highlight selected + mvprintw(i+2, 2, "%s", options[i]); + if (i == highlight) { + attroff(A_REVERSE); + } + } + key = getch(); //get some int which value correspond to some key being pressed + + switch(key) { + case KEY_UP: + case 'w': + case 'W': + highlight--; + if (highlight < 0) { + highlight = optionsNumber - 1;// can't select the -1nth option + } + break; + case 's': + case 'S': + case KEY_DOWN: + highlight++; + if (highlight >= optionsNumber) { + highlight = 0; + } + break; + case 10: //\n + choice = highlight; + goto end_loop; + } + } + end_loop: + endwin(); // end ncurses mode + return options[choice]; +} + +int compareString(const void *a, const void *b) { // this will be the function used by qsort + const char *str1 = *(const char **)a; + const char *str2 = *(const char **)b; + return strcmp(str1, str2); // strcmp returns <0, 0, >0 +} + int main() { // Read config file @@ -44,33 +186,42 @@ int main() { } else { notesDirectoryString = "~/Documents/Notes/"; // default } - - // (TODO LATER) it might be a good idea to check if these directories exist - // (TODO LATER) expand ~ as it does not work with opendir() - printf("Opening %s\n", notesDirectoryString); - - //--------------------------------------------------------------------------------------- - // https://www.geeksforgeeks.org/c/c-program-list-files-sub-directories-directory/ - struct dirent *notesDirectoryEntry; - DIR *notesDirectory = opendir(notesDirectoryString); - if (notesDirectory == NULL) // opendir returns NULL if couldn't open directory - { - printf("Could not open current directory" ); - return 1; + size_t vaultsCount = 0; + char **vaultsArray = getVaultsFromDirectory(notesDirectoryString, &vaultsCount); + qsort(vaultsArray, vaultsCount, sizeof(const char *), compareString); // sorts the vaults alphabetically + printf("Available vaults:\n"); + for (size_t i = 0; i < vaultsCount; i++) { + printf("%s\n", vaultsArray[i]); } - // Refer https://pubs.opengroup.org/onlinepubs/7990989775/xsh/readdir.html - // for readdir() - while ((notesDirectoryEntry = readdir(notesDirectory)) != NULL) - printf("%s\n", notesDirectoryEntry->d_name); + + // adds "create a new vault" into the vaultsArray + // (TODO LATER) maybe add an option for setting + const int extraOptions = 2; + vaultsArray = realloc(vaultsArray, (vaultsCount + extraOptions)*sizeof(char*)); // resize dirsArray so that + // (TODO LATER) add a way to Colorize the extraOptions + vaultsArray[vaultsCount] = "Create a new vault"; // some more options that are not vaults + vaultsArray[vaultsCount+1] = "Settings"; + // select a vault + char *vaultSelected = ncursesSelect(vaultsArray, "vault", vaultsCount + extraOptions); + printf("Selected vault:%s\n", vaultSelected); + + if (vaultSelected != "Create a new vault" || vaultSelected != "Settings") { + int filesCount = 0; + char **filesArray = getNotesFromVault(notesDirectoryString, vaultSelected, &filesCount); + qsort(filesArray, filesCount, sizeof(const char *), compareString); // sorts the notes alphabetically + // + printf("Available notes:\n"); + for (size_t i = 0; i < filesCount; i++) { + printf("%s\n", filesArray[i]); + } + } else if (vaultSelected == "Create a new vault") { - - //-------------------------------------------------------------------------------------- - - // list all the directories (except hidden ones). They are like obsidian vaults + } else if (vaultSelected == "Settings") { + //(TODO LATER) add a way to change the config.json from the app or at least show all the options + } // Cleanup if (dirJsonFormat && notesDirectoryString != dirJsonFormat->valuestring) free(notesDirectoryString); // only free strdup - closedir(notesDirectory); cJSON_Delete(json); free(data);