From 07f503dc5b9ab465666f66d486065839e0dcb044 Mon Sep 17 00:00:00 2001 From: Tomas Rivera <137088692+Totorile1@users.noreply.github.com> Date: Sat, 4 Apr 2026 11:36:59 +0200 Subject: [PATCH] createNewNote() now works with journals --- src/main.c | 9 ++++-- src/notes.c | 2 ++ src/ui.c | 86 +++++++++++++++++++++++++++++++++++++++++------------ src/ui.h | 6 ++-- 4 files changed, 79 insertions(+), 24 deletions(-) diff --git a/src/main.c b/src/main.c index ed218d9..4383cb0 100644 --- a/src/main.c +++ b/src/main.c @@ -287,21 +287,24 @@ open_note: debug("%s is a journal. Updating it...", noteSelected); fullPath = updateJournal(fullPath, noteSelected, timeFormat, shouldDebug); // we return the path. As if it is a divided journal we must point to the correct entry } - if (newLineOnOpening) { //(TODO LATER) For some reason this does not applies to journals? + if (newLineOnOpening) { //(TODO LATER) For some reason this does not applies to journals? --- it does but only if we don't create a new file/entry appendToFile(fullPath, "\n", shouldDebug); } openEditor(fullPath, editorToOpen, shouldRender, shouldJumpToEnd, shouldDebug); free(fullPath); } else if (strcmp(noteSelected,"Create new note") == 0) { note_creation: - char *pathForNoteCreation = createNewNote(notesDirectoryString, vaultSelected, bypassNoteSelection, shouldDebug); + noteSelected = createNewNote(notesDirectoryString, vaultSelected, bypassNoteSelection, journalRegex, shouldDebug); + // we can just go back to open_note + goto open_note; + /*char *pathForNoteCreation = createNewNote(notesDirectoryString, vaultSelected, bypassNoteSelection, shouldDebug); // (TODO LATER) Handle journal creation bypassNoteSelection = HASH_MACRO; // we must reset bypassNoteSelection to avoid getting into an infinite loop of bypassing the note selection if (newLineOnOpening) { appendToFile(pathForNoteCreation, "\n", shouldDebug); } openEditor(pathForNoteCreation, editorToOpen, shouldRender, shouldJumpToEnd, shouldDebug); - //free(pathForNoteCreation); + //free(pathForNoteCreation);*/ } else if (strcmp(noteSelected,"Back to vault selection") == 0) { shouldChangeVault = 1; } else if (strcmp(noteSelected, "Delete vault") == 0) { diff --git a/src/notes.c b/src/notes.c index 30c6f3a..d0b0746 100644 --- a/src/notes.c +++ b/src/notes.c @@ -202,6 +202,8 @@ char *updateJournal(char *path, char *journal, char *timeFormat, int shouldDebug fprintf(file, "%s\n", date); fclose(file); free(createEntryMessage); + } else { + debug("Today's entry (%s) already exist. We won't create a new one.", dateWithExtension); } } else { // we just recreate the path to the selected entry // snprintf does not like to have the same variable as input and output so we use a buffer diff --git a/src/ui.c b/src/ui.c index 470b87a..0b4dfc8 100644 --- a/src/ui.c +++ b/src/ui.c @@ -46,45 +46,93 @@ input_screen: } -char *createNewNote(char dirToVault[PATH_MAX], char *vaultFromDir, char *bypass, int shouldDebug) { +char *createNewNote(char dirToVault[PATH_MAX], char *vaultFromDir, char *bypass, char *journalRegex, int shouldDebug) { // (TODO LATER) Add code to create journal // (TODO LATER) Add check. If the user creates a note with a name that already exists. it erases the old one // input from user for the name - char fileName[256]; + char *fileName = malloc(BUFFER_SIZE); if (strcmp(bypass, HASH_MACRO) == 0) { initscr(); echo(); keypad(stdscr, FALSE); clear(); printw("Enter the name of the new note: "); - mvprintw(3, 0, "Unsafe characters such as \\, and / will be replaced by _"); // (TODO LATER) add more info + mvprintw(3, 0, "Unsafe characters such as \\, and / will be replaced by _"); + mvprintw(4, 0, "If the name matches with the regex for a journal (%s), it will create a journal instead of a note.", journalRegex); move(1,1); - wgetnstr(stdscr, fileName, sizeof(fileName)-4); //limits the buffer to prevent overflow (-4 to account indexing and from ".md" in case we need to add it later) + wgetnstr(stdscr, fileName, BUFFER_SIZE-4); //limits the buffer to prevent overflow (-4 to account indexing and from ".md" in case we need to add it later) refresh(); endwin(); } else { // bypasses user input if we bypass is different than HASH_MACRO - strncpy(fileName, bypass, sizeof(fileName)-1); // (TODO LATER) Maybe add a warning if string is too big. It gets truncated - fileName[sizeof(fileName)-1] = '\0'; + strncpy(fileName, bypass, BUFFER_SIZE-1); // (TODO LATER) Maybe add a warning if string is too big. It gets truncated + fileName[BUFFER_SIZE-1] = '\0'; } // (TODO LATER) add a way to go back to note selection error(strcmp(fileName, "") == 0, "user", "fileName is empty"); // replace this with a warning and add a warning if duplicate file and handle case where multiple warnings (if such case is possible) // check/sanitize the input debug("Inputed fileName=%s", fileName); sanitize(fileName); - // if there is no .md add an .md - int len = strlen(fileName); - if (fileName[len-1] != 'd' || fileName[len-2] != 'm' || fileName[len-3] != '.') { // there might be a cleaner way to do this - strcat(fileName, ".md"); // this should not cause an overflow issue as we get at most 252 chars (+'.'+'m'+'d'+'\0' makes it to 256) with wgetnstr + debug("Sanitized fileName=%s (We might append .md later", fileName); + // if it matches with the journalRegex we treat it as a journal instead of a note + regex_t regex; + int regexReturn = regcomp(®ex, journalRegex, 0); + error(regexReturn, "program", "Regex compilation failed."); + regexReturn = regexec(®ex, fileName, 0, NULL, 0); // (TODO LATER) This might be an extrem edge case but + // if journalRegex is something like [...].md + // and the inputed file name does not match it + // we create it as a note + // but if fileName + ".md" matches the regex + // we will open it as a journal + if (!regexReturn) { + debug("%s matches with %s treating it as a journal", fileName, journalRegex); + char **options = malloc(32); // the number of bytes is exactly what in the two strings // (TODO LATER) There might be a cleaner way + options[0] = "Divided journal"; + options[1] = "Unified journal"; + char *optionSelected = ncursesSelect(options, "Select which type of journal you want to create (Use arrows or WASD, Enter to select):", 2, 0, "", "", " ", shouldDebug); + debug("%s was selected to be a %s", fileName, optionSelected); + if (strcmp(optionSelected, options[0]) == 0) { // if it is a divided journal + char *fileFullPath = malloc(PATH_MAX); // (TODO LATER) we use a lot of malloc. We should check for memory leaks + snprintf(fileFullPath, PATH_MAX, "%s/%s/%s/", dirToVault, vaultFromDir, fileName); + struct stat st = {0}; + if (stat(fileFullPath, &st) == -1) { + mkdir(fileFullPath, 0744); // (TODO LATER) might wanna add an error if we couldn't create the dir + } else { + error(1, "program", "%s could not be created", fileFullPath); + } + free(fileFullPath); + } else { // if it is a unified journal + char *fileFullPath = malloc(PATH_MAX); + // we must add .md if it doesn't have // (TODO LATER) add a warning to the journalRegex. It must match with fileName and fileName + ".md" in case we append the extension + int len = strlen(fileName); + if (fileName[len-3] != '.' || fileName[len-2] != 'm' || fileName[len-1] != 'd') { // there might be a cleaner way to do this + strncat(fileName, ".md", PATH_MAX); + } + snprintf(fileFullPath, PATH_MAX, "%s/%s/%s", dirToVault, vaultFromDir, fileName); + FILE *filePointer; + filePointer = fopen(fileFullPath, "w"); // creates and opens the file (TODO LATER) Maybe check if the file really doesn't exist + error(filePointer == NULL, "program", "The %s couldn't be created.", fileFullPath); + fprintf(filePointer, "### %s\n", fileName); //(TODO LATER) Add a way to configure default behaviour when creating a file + fclose(filePointer); // closes the file so that nvim could open it + free(fileFullPath); + } + free(options); // they are useless now + } else { // normal process for a note + debug("%s does not match with %s treating it as a note", fileName, journalRegex); + // if there is no .md add an .md + int len = strlen(fileName); + if (fileName[len-3] != '.' || fileName[len-2] != 'm' || fileName[len-1] != 'd') { // there might be a cleaner way to do this + strcat(fileName, ".md"); // this should not cause an overflow issue as we get at most 252 chars (+'.'+'m'+'d'+'\0' makes it to 256) with wgetnstr + } + char *fileFullPath = malloc(PATH_MAX); // this dinamically allocated because we use it in the main function to call openEditor + sprintf(fileFullPath, "%s/%s/%s", dirToVault, vaultFromDir, fileName); + FILE *filePointer; + filePointer = fopen(fileFullPath, "w"); // creates and opens the file (TODO LATER) Maybe check if the file really doesn't exist + error(filePointer == NULL, "program", "The %s couldn't be created.", fileFullPath); + fprintf(filePointer, "### %s\n", fileName); //(TODO LATER) Add a way to configure default behaviour when creating a file + fclose(filePointer); // closes the file so that nvim could open it + free(fileFullPath); } - debug("Sanitized fileName=%s", fileName); - char *fileFullPath = malloc(PATH_MAX); // this dinamically allocated because we use it in the main function to call openEditor - sprintf(fileFullPath, "%s/%s/%s", dirToVault, vaultFromDir, fileName); - FILE *filePointer; - filePointer = fopen(fileFullPath, "w"); // creates and opens the file (TODO LATER) Maybe check if the file really doesn't exist - error(filePointer == NULL, "program", "The %s couldn't be created.", fileFullPath); - fprintf(filePointer, "### %s\n", fileName); //(TODO LATER) Add a way to configure default behaviour when creating a file - fclose(filePointer); // closes the file so that nvim could open it - return fileFullPath; + return fileName; } char* ncursesSelect(char **options, char *optionsText, size_t optionsNumber, size_t extraOptionsNumber, char *bottomText, char *middleText, char *topText, int shouldDebug) { diff --git a/src/ui.h b/src/ui.h index a201580..164cbc5 100644 --- a/src/ui.h +++ b/src/ui.h @@ -10,11 +10,13 @@ #include #include #include +#include #include "utils.h" -char *createNewNote(char dirToVault[PATH_MAX], char *vaultFromDir, char *bypass, int debug); +char *createNewNote(char dirToVault[PATH_MAX], char *vaultFromDir, char *bypass, char *journalRegex, int debug); // Uses ncurses to get an input from the user // Creates a new note with this input -// returns the path to the note +// also can create a journal if the name matches with journalRegex +// returns the name of the note void createNewVault(char *dirToVault, int debug); // Uses ncurses to get an input from the user // Creates a new vault with this input