mirror of
https://github.com/tomasriveral/NoteWrapper.git
synced 2026-08-12 02:18:38 +02:00
coded the vault and note selector
This commit is contained in:
@@ -4,6 +4,7 @@ pkgs.mkShell {
|
|||||||
buildInputs = [
|
buildInputs = [
|
||||||
pkgs.vivify
|
pkgs.vivify
|
||||||
pkgs.cjson
|
pkgs.cjson
|
||||||
|
pkgs.ncurses
|
||||||
pkgs.pkg-config
|
pkgs.pkg-config
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,150 @@
|
|||||||
|
//gcc startup.c $(pkg-config --cflags --libs libcjson ncurses)
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <cjson/cJSON.h>
|
#include <cjson/cJSON.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <limits.h> // for PATH_MAX
|
||||||
|
#include <ncurses.h>
|
||||||
|
|
||||||
|
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() {
|
int main() {
|
||||||
// Read config file
|
// Read config file
|
||||||
@@ -44,33 +186,42 @@ int main() {
|
|||||||
} else {
|
} else {
|
||||||
notesDirectoryString = "~/Documents/Notes/"; // default
|
notesDirectoryString = "~/Documents/Notes/"; // default
|
||||||
}
|
}
|
||||||
|
size_t vaultsCount = 0;
|
||||||
// (TODO LATER) it might be a good idea to check if these directories exist
|
char **vaultsArray = getVaultsFromDirectory(notesDirectoryString, &vaultsCount);
|
||||||
// (TODO LATER) expand ~ as it does not work with opendir()
|
qsort(vaultsArray, vaultsCount, sizeof(const char *), compareString); // sorts the vaults alphabetically
|
||||||
printf("Opening %s\n", notesDirectoryString);
|
printf("Available vaults:\n");
|
||||||
|
for (size_t i = 0; i < vaultsCount; i++) {
|
||||||
//---------------------------------------------------------------------------------------
|
printf("%s\n", vaultsArray[i]);
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
// 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
|
// Cleanup
|
||||||
if (dirJsonFormat && notesDirectoryString != dirJsonFormat->valuestring) free(notesDirectoryString); // only free strdup
|
if (dirJsonFormat && notesDirectoryString != dirJsonFormat->valuestring) free(notesDirectoryString); // only free strdup
|
||||||
closedir(notesDirectory);
|
|
||||||
cJSON_Delete(json);
|
cJSON_Delete(json);
|
||||||
free(data);
|
free(data);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user