mirror of
https://github.com/tomasriveral/NoteWrapper.git
synced 2026-08-12 10:20:46 +02:00
Unified journals are now supported!
This commit is contained in:
@@ -47,3 +47,4 @@ Change `$/.config/notewrapper/config.json`. If it does not exist. On building, i
|
|||||||
- [ ] Fixe all the small stuff marked //(TODO LATER) in the code
|
- [ ] Fixe all the small stuff marked //(TODO LATER) in the code
|
||||||
- [ ] Add a way to delete notes
|
- [ ] Add a way to delete notes
|
||||||
- [ ] Comply with GPL-3 notice (add info about no waranty, etc.)
|
- [ ] Comply with GPL-3 notice (add info about no waranty, etc.)
|
||||||
|
- [ ] A converter for both type of journals
|
||||||
|
|||||||
+3
-1
@@ -3,5 +3,7 @@
|
|||||||
"render": true,
|
"render": true,
|
||||||
"jumpToEndOfFileOnLaunch": true,
|
"jumpToEndOfFileOnLaunch": true,
|
||||||
"editor": "neovim",
|
"editor": "neovim",
|
||||||
"journalRegex": ".*journal.*"
|
"journalRegex": ".*journal.*",
|
||||||
|
"dateEntry": "# %a %d %m %Y",
|
||||||
|
"newLineOnOpening": true
|
||||||
}
|
}
|
||||||
|
|||||||
+42
-7
@@ -83,25 +83,43 @@ int main(int argc, char *argv[]) {
|
|||||||
cJSON *shouldRenderJSON = cJSON_GetObjectItem(json, "render");
|
cJSON *shouldRenderJSON = cJSON_GetObjectItem(json, "render");
|
||||||
if (shouldRenderJSON && cJSON_IsBool(shouldRenderJSON)) {
|
if (shouldRenderJSON && cJSON_IsBool(shouldRenderJSON)) {
|
||||||
shouldRender = cJSON_IsTrue(shouldRenderJSON) ? 1 : 0;
|
shouldRender = cJSON_IsTrue(shouldRenderJSON) ? 1 : 0;
|
||||||
}
|
} else {debug("config.json did not contained a correct \"render\" value. The default is 1.");}
|
||||||
|
|
||||||
int shouldJumpToEnd = 1;
|
int shouldJumpToEnd = 1;
|
||||||
cJSON *shouldJumpToEndJSON = cJSON_GetObjectItem(json, "jumpToEndOfFileOnLaunch");
|
cJSON *shouldJumpToEndJSON = cJSON_GetObjectItem(json, "jumpToEndOfFileOnLaunch");
|
||||||
if (shouldJumpToEndJSON && cJSON_IsBool(shouldJumpToEndJSON)) {
|
if (shouldJumpToEndJSON && cJSON_IsBool(shouldJumpToEndJSON)) {
|
||||||
shouldJumpToEnd = cJSON_IsTrue(shouldJumpToEndJSON) ? 1 : 0;
|
shouldJumpToEnd = cJSON_IsTrue(shouldJumpToEndJSON) ? 1 : 0;
|
||||||
}
|
} else {debug("config.json did not contained a correct \"jumpToEndOfFileOnLaunch\" value. The default is 1.");}
|
||||||
|
|
||||||
char *editorToOpen = "neovim"; // default
|
char *editorToOpen = "neovim"; // default
|
||||||
cJSON *editorToOpenJSON = cJSON_GetObjectItem(json, "editor");
|
cJSON *editorToOpenJSON = cJSON_GetObjectItem(json, "editor");
|
||||||
if (editorToOpenJSON || cJSON_IsString(editorToOpenJSON)) {
|
if (editorToOpenJSON && cJSON_IsString(editorToOpenJSON)) {
|
||||||
debug("Editor in config.json is %s", editorToOpenJSON->valuestring);
|
debug("Editor in config.json is %s", editorToOpenJSON->valuestring);
|
||||||
error(!isStringInArray(editorToOpenJSON->valuestring, supportedEditor, numEditors), "user", "%s (fetched from config.json) is not a supported editor.");
|
error(!isStringInArray(editorToOpenJSON->valuestring, supportedEditor, numEditors), "user", "%s (fetched from config.json) is not a supported editor.");
|
||||||
editorToOpen = strdup(editorToOpenJSON->valuestring); // we must strdup and not just = as we will free all the json after (before parsing args)
|
editorToOpen = strdup(editorToOpenJSON->valuestring); // we must strdup and not just = as we will free all the json after (before parsing args)
|
||||||
}
|
} else {debug("config.json did not contained a correct \"editor\" value. The default is neovim.");}
|
||||||
|
|
||||||
cJSON *journalRegexJSON = cJSON_GetObjectItem(json, "journalRegex");
|
cJSON *journalRegexJSON = cJSON_GetObjectItem(json, "journalRegex");
|
||||||
char *journalRegex = ".*journal.*"; // default regex pattern for the journal
|
char *journalRegex = ".*journal.*"; // default regex pattern for the journal
|
||||||
if (journalRegexJSON || cJSON_IsString(journalRegexJSON)) {
|
if (journalRegexJSON && cJSON_IsString(journalRegexJSON)) {
|
||||||
debug("The regex in config.json is %s", journalRegexJSON->valuestring);
|
debug("The regex in config.json is %s", journalRegexJSON->valuestring);
|
||||||
journalRegex = strdup(journalRegexJSON->valuestring);
|
journalRegex = strdup(journalRegexJSON->valuestring);
|
||||||
}
|
} else {debug("config.json did not contained a correct \"journalRegex\" value. The default is .*journal.*");}
|
||||||
|
|
||||||
|
char *timeFormat = "# \%a \%d \%m \%Y";// default
|
||||||
|
cJSON *timeFormatJSON = cJSON_GetObjectItem(json, "dateEntry");
|
||||||
|
if (timeFormatJSON && cJSON_IsString(timeFormatJSON)) {
|
||||||
|
debug("The time format in config.json is %s", timeFormatJSON->valuestring);
|
||||||
|
timeFormat = strdup(timeFormatJSON->valuestring);
|
||||||
|
} else {debug("config.json did not contained a correct \"dateEntry\" value. The default is \"# \%a \%d \%m \%Y\".");}
|
||||||
|
|
||||||
|
int newLineOnOpening = 1;
|
||||||
|
cJSON *newLineOnOpeningJSON = cJSON_GetObjectItem(json, "newLineOnOpening");
|
||||||
|
if (newLineOnOpeningJSON && cJSON_IsBool(newLineOnOpeningJSON)) {
|
||||||
|
debug("The value for newLineOnOpening in config.json is %d", cJSON_IsTrue(newLineOnOpeningJSON));
|
||||||
|
newLineOnOpening = cJSON_IsTrue(newLineOnOpeningJSON) ? 1 : 0;
|
||||||
|
} else {debug("config.json did not contained a correct \"newLineOnOpening\" value. The default is true.");}
|
||||||
|
|
||||||
//cleans up
|
//cleans up
|
||||||
cJSON_Delete(json);
|
cJSON_Delete(json);
|
||||||
free(data);
|
free(data);
|
||||||
@@ -258,13 +276,30 @@ note_selection:
|
|||||||
if (strcmp(noteSelected, "Create new note") != 0 && strcmp(noteSelected,"Back to vault selection") != 0 && strcmp(noteSelected, "Delete vault") != 0 && strcmp(noteSelected,"Quit (Ctrl+C)") != 0) {
|
if (strcmp(noteSelected, "Create new note") != 0 && strcmp(noteSelected,"Back to vault selection") != 0 && strcmp(noteSelected, "Delete vault") != 0 && strcmp(noteSelected,"Quit (Ctrl+C)") != 0) {
|
||||||
open_note:
|
open_note:
|
||||||
bypassNoteSelection = HASH_MACRO; // we must reset bypassNoteSelection to avoid getting into an infinite loop of bypassing the note selection
|
bypassNoteSelection = HASH_MACRO; // we must reset bypassNoteSelection to avoid getting into an infinite loop of bypassing the note selection
|
||||||
char fullPath[PATH_MAX]; // (TODO LATER) Find a more appropriate and descriptive name for the variable
|
char *fullPath = malloc(PATH_MAX); // (TODO LATER) Find a more appropriate and descriptive name for the variable
|
||||||
sprintf(fullPath, "%s/%s/%s", notesDirectoryString, vaultSelected, noteSelected); // (TODO LATER) change all sprintf to snprintf which checks for buffer size
|
sprintf(fullPath, "%s/%s/%s", notesDirectoryString, vaultSelected, noteSelected); // (TODO LATER) change all sprintf to snprintf which checks for buffer size
|
||||||
|
// if it is a journal we must update it before
|
||||||
|
regex_t regex;
|
||||||
|
int regexReturn = regcomp(®ex, journalRegex, 0);
|
||||||
|
error(regexReturn, "program", "Regex compilation failed.");
|
||||||
|
regexReturn = regexec(®ex, noteSelected, 0, NULL, 0);
|
||||||
|
if (!regexReturn) { // if the regex matches -> it's a journal
|
||||||
|
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?
|
||||||
|
appendToFile(fullPath, "\n", shouldDebug);
|
||||||
|
}
|
||||||
openEditor(fullPath, editorToOpen, shouldRender, shouldJumpToEnd, shouldDebug);
|
openEditor(fullPath, editorToOpen, shouldRender, shouldJumpToEnd, shouldDebug);
|
||||||
|
free(fullPath);
|
||||||
} else if (strcmp(noteSelected,"Create new note") == 0) {
|
} else if (strcmp(noteSelected,"Create new note") == 0) {
|
||||||
note_creation:
|
note_creation:
|
||||||
char *pathForNoteCreation = createNewNote(notesDirectoryString, vaultSelected, bypassNoteSelection, shouldDebug);
|
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
|
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);
|
openEditor(pathForNoteCreation, editorToOpen, shouldRender, shouldJumpToEnd, shouldDebug);
|
||||||
//free(pathForNoteCreation);
|
//free(pathForNoteCreation);
|
||||||
} else if (strcmp(noteSelected,"Back to vault selection") == 0) {
|
} else if (strcmp(noteSelected,"Back to vault selection") == 0) {
|
||||||
|
|||||||
+111
-87
@@ -1,6 +1,96 @@
|
|||||||
#include "notes.h"
|
#include "notes.h"
|
||||||
|
|
||||||
char** getVaultsFromDirectory(char *dirString, size_t *count, int shouldDebug) {
|
char **getJournalsFromVault(char *pathToVault, char *vault, char *journalRegex, int *count, int shouldDebug) {
|
||||||
|
debug("Searching %s for journals", vault);
|
||||||
|
// originally from https://www.geeksforgeeks.org/c/c-program-list-files-sub-directories-directory/
|
||||||
|
struct dirent *vaultEntry;
|
||||||
|
char tempPath[PATH_MAX];
|
||||||
|
snprintf(tempPath, sizeof(tempPath), "%s/%s", pathToVault, vault); // sets the full absolute path to fullPathEntry
|
||||||
|
DIR *vaultDirectory = opendir(tempPath);
|
||||||
|
error(vaultDirectory==NULL, "program", "Could not open directory %s", tempPath);
|
||||||
|
char **journalsArray = NULL; // will contain all the notes
|
||||||
|
size_t journalsCount = 0; // we need to count how many notes there is to always readjust how many memory we alloc
|
||||||
|
|
||||||
|
// https://stackoverflow.com/a/1085120 for regex code
|
||||||
|
regex_t regex;
|
||||||
|
int regexReturn;
|
||||||
|
// compiles the regex
|
||||||
|
regexReturn = regcomp(®ex, journalRegex, 0);
|
||||||
|
error(regexReturn, "program", "Regex could not compile. Perhaps there is an error with the regex string");
|
||||||
|
debug("Regex compiled succesfully");
|
||||||
|
// Refer https://pubs.opengroup.org/onlinepubs/7990989775/xsh/readdir.html
|
||||||
|
// for readdir()
|
||||||
|
debug("┌------------------------------------------\nDetected files and dirs from the vault");
|
||||||
|
while ((vaultEntry = readdir(vaultDirectory)) != NULL) { // we iterate over every entry from the dir. So files and dirs (. and .. included)
|
||||||
|
altDebug("%s ", vaultEntry->d_name);
|
||||||
|
// (TODO LATER) check if it is a file or a dir
|
||||||
|
if (vaultEntry->d_name[0] != '.') { // if the entry don't start with a dot (so hidden dirs and hidden files)
|
||||||
|
regexReturn = regexec(®ex, vaultEntry->d_name, 0, NULL, 0);
|
||||||
|
if (!regexReturn) { // if the regex matches
|
||||||
|
altDebug("matched with the regex. It is a journal.\n");
|
||||||
|
journalsArray = realloc(journalsArray, (journalsCount + 1)*sizeof(char*)); // resize notesArray so that
|
||||||
|
journalsArray[journalsCount] = strdup(vaultEntry->d_name); // copy the dir name into notesArray
|
||||||
|
journalsCount++;
|
||||||
|
} else {
|
||||||
|
altDebug("did not matched with the regex. It is a note.\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
altDebug(" was ignored\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
altDebug("└ ------------------------------\n");
|
||||||
|
// free's some used memory
|
||||||
|
closedir(vaultDirectory);
|
||||||
|
*count = journalsCount; // passes the number of files
|
||||||
|
return journalsArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
char** getNotesFromVault(char *pathToVault, char *vault, char *journalRegex, int *count, int shouldDebug) {
|
||||||
|
// this function is inputed a path to a vault (which was selected before) and outpus all the suitable notes (so not the hidden ones)
|
||||||
|
// (TODO LATER) Check how it handles non .md files
|
||||||
|
// originally from https://www.geeksforgeeks.org/c/c-program-list-files-sub-directories-directory/
|
||||||
|
debug("Searching %s for notes", vault);
|
||||||
|
struct dirent *vaultEntry; // (TODO LATER) change name of these variables. notesDirectory is dumb as it is the directory of vaults
|
||||||
|
char tempPath[PATH_MAX];
|
||||||
|
snprintf(tempPath, sizeof(tempPath), "%s/%s", pathToVault, vault); // sets the full absolute path to fullPathEntry
|
||||||
|
DIR *vaultDirectory = opendir(tempPath);
|
||||||
|
error(vaultDirectory==NULL, "program", "Could not open directory %s", tempPath);
|
||||||
|
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()
|
||||||
|
debug("┌------------------------------\nDetected Files and dirs from the vault:");
|
||||||
|
while ((vaultEntry = readdir(vaultDirectory)) != NULL) {
|
||||||
|
|
||||||
|
altDebug("%s ", vaultEntry->d_name);
|
||||||
|
// for the regex code https://stackoverflow.com/a/1085120
|
||||||
|
regex_t regex;
|
||||||
|
int regexReturn;
|
||||||
|
// compiles the regex
|
||||||
|
regexReturn = regcomp(®ex, journalRegex, 0);
|
||||||
|
if (vaultEntry->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, vaultEntry->d_name); // sets the full absolute path to fullPathEntry
|
||||||
|
// check if it matches the regex. If it does not match regexReturn != 0.
|
||||||
|
regexReturn = regexec(®ex, vaultEntry->d_name, 0, NULL, 0);
|
||||||
|
struct stat metadataPathEntry;
|
||||||
|
if (stat(fullPathEntry, &metadataPathEntry) == 0 && regexReturn && S_ISREG(metadataPathEntry.st_mode)) { // if this entry is a file
|
||||||
|
notesArray = realloc(notesArray, (notesCount + 1)*sizeof(char*)); // resize notesArray so that
|
||||||
|
notesArray[notesCount] = strdup(vaultEntry->d_name); // copy the dir name into notesArray
|
||||||
|
notesCount++;
|
||||||
|
altDebug("did not match with the regex. It is a note.\n");
|
||||||
|
} else if (!regexReturn) {altDebug("matched with the regex. It is a journal.\n");}
|
||||||
|
} else {altDebug("was ignored\n");}
|
||||||
|
}
|
||||||
|
altDebug("└ ------------------------------\n");
|
||||||
|
// (TODO LATER) Alphabetically sort them
|
||||||
|
// free's some used memory
|
||||||
|
closedir(vaultDirectory);
|
||||||
|
*count = notesCount; // passes the number of files
|
||||||
|
return notesArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
char **getVaultsFromDirectory(char *dirString, size_t *count, int shouldDebug) {
|
||||||
// (TODO LATER) it might be a good idea to check if these directories exist
|
// (TODO LATER) it might be a good idea to check if these directories exist
|
||||||
// (TODO LATER) expand ~ as it does not work with opendir()
|
// (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
|
// 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
|
||||||
@@ -37,93 +127,27 @@ char** getVaultsFromDirectory(char *dirString, size_t *count, int shouldDebug) {
|
|||||||
return dirsArray;
|
return dirsArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *updateJournal(char *path, char *journal, char *timeFormat, int shouldDebug) {
|
||||||
|
//(TODO LATER) Per journal format configuration
|
||||||
|
// (TODO LATER) with all the usage of PATH_MAX we should really calculate max inputed path or something like this
|
||||||
|
path[PATH_MAX] = '\0'; // it assures it is a string (Most cases this does nothing). But rewriting at least one bytes make the compile happy. He doesn't want to return an unchanged input.
|
||||||
|
debug("Handling the journal %s", path);
|
||||||
|
|
||||||
char** getNotesFromVault(char *pathToVault, char *vault, char *journalRegex, int *count, int shouldDebug) {
|
char *date = getFormatedTime(timeFormat, shouldDebug);
|
||||||
// this function is inputed a path to a vault (which was selected before) and outpus all the suitable notes (so not the hidden ones)
|
debug("Formated time for the journal's entry is %s", date);
|
||||||
// (TODO LATER) Check how it handles non .md files
|
|
||||||
// originally from https://www.geeksforgeeks.org/c/c-program-list-files-sub-directories-directory/
|
|
||||||
debug("Searching %s for notes", vault);
|
|
||||||
struct dirent *vaultEntry; // (TODO LATER) change name of these variables. notesDirectory is dumb as it is the directory of vaults
|
|
||||||
char tempPath[PATH_MAX];
|
|
||||||
snprintf(tempPath, sizeof(tempPath), "%s/%s", pathToVault, vault); // sets the full absolute path to fullPathEntry
|
|
||||||
DIR *vaultDirectory = opendir(tempPath);
|
|
||||||
error(vaultDirectory==NULL, "program", "Could not open directory %s", tempPath);
|
|
||||||
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()
|
|
||||||
debug("┌------------------------------\nDetected Files and dirs from the vault:");
|
|
||||||
while ((vaultEntry = readdir(vaultDirectory)) != NULL) {
|
|
||||||
|
|
||||||
altDebug("%s ", vaultEntry->d_name);
|
struct stat metadata;
|
||||||
// for the regex code https://stackoverflow.com/a/1085120
|
error(stat(path, &metadata), "program", "stat() failed to get information about %s", path);
|
||||||
regex_t regex;
|
if (S_ISREG(metadata.st_mode)) {
|
||||||
int regexReturn;
|
debug("%s is a unified journal.", path);
|
||||||
// compiles the regex
|
if (!isStringInFile(path, date, shouldDebug)) { // if there is no entry for current date
|
||||||
regexReturn = regcomp(®ex, journalRegex, 0);
|
appendToFile(path, date, shouldDebug);
|
||||||
if (vaultEntry->d_name[0] != '.') { // if the entry don't start with a dot (so hidden dirs and hidden files)
|
} // if there is an entry do nothing
|
||||||
char fullPathEntry[PATH_MAX]; // creates a string of size of the maximum path lenght
|
} else if (S_ISDIR(metadata.st_mode)) {
|
||||||
snprintf(fullPathEntry, sizeof(fullPathEntry), "%s/%s/%s", pathToVault, vault, vaultEntry->d_name); // sets the full absolute path to fullPathEntry
|
debug("%s is a divided journal.", path);
|
||||||
// check if it matches the regex. If it does not match regexReturn != 0.
|
|
||||||
regexReturn = regexec(®ex, vaultEntry->d_name, 0, NULL, 0);
|
|
||||||
struct stat metadataPathEntry;
|
|
||||||
if (stat(fullPathEntry, &metadataPathEntry) == 0 && regexReturn && !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(vaultEntry->d_name); // copy the dir name into notesArray
|
|
||||||
notesCount++;
|
|
||||||
altDebug("did not match with the regex. It is a note.\n");
|
|
||||||
} else if (!regexReturn) {altDebug("matched with the regex. It is a journal.\n");}
|
|
||||||
} else {altDebug("was ignored\n");}
|
|
||||||
}
|
|
||||||
altDebug("└ ------------------------------\n");
|
|
||||||
// (TODO LATER) Alphabetically sort them
|
|
||||||
// free's some used memory
|
|
||||||
closedir(vaultDirectory);
|
|
||||||
*count = notesCount; // passes the number of files
|
|
||||||
return notesArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
} else {
|
||||||
char **getJournalsFromVault(char *pathToVault, char *vault, char *journalRegex, int *count, int shouldDebug) {
|
error(1, "program", "%s is not a file and not a directory.", path);
|
||||||
debug("Searching %s for journals", vault);
|
}
|
||||||
// originally from https://www.geeksforgeeks.org/c/c-program-list-files-sub-directories-directory/
|
return path;
|
||||||
struct dirent *vaultEntry;
|
|
||||||
char tempPath[PATH_MAX];
|
|
||||||
snprintf(tempPath, sizeof(tempPath), "%s/%s", pathToVault, vault); // sets the full absolute path to fullPathEntry
|
|
||||||
DIR *vaultDirectory = opendir(tempPath);
|
|
||||||
error(vaultDirectory==NULL, "program", "Could not open directory %s", tempPath);
|
|
||||||
char **journalsArray = NULL; // will contain all the notes
|
|
||||||
size_t journalsCount = 0; // we need to count how many notes there is to always readjust how many memory we alloc
|
|
||||||
|
|
||||||
// https://stackoverflow.com/a/1085120 for regex code
|
|
||||||
regex_t regex;
|
|
||||||
int regexReturn;
|
|
||||||
// compiles the regex
|
|
||||||
regexReturn = regcomp(®ex, journalRegex, 0);
|
|
||||||
error(regexReturn, "program", "Regex could not compile. Perhaps there is an error with the regex string");
|
|
||||||
debug("Regex compiled succesfully");
|
|
||||||
// Refer https://pubs.opengroup.org/onlinepubs/7990989775/xsh/readdir.html
|
|
||||||
// for readdir()
|
|
||||||
debug("┌------------------------------------------\nDetected files and dirs from the vault");
|
|
||||||
while ((vaultEntry = readdir(vaultDirectory)) != NULL) { // we iterate over every entry from the dir. So files and dirs (. and .. included)
|
|
||||||
altDebug("%s ", vaultEntry->d_name);
|
|
||||||
if (vaultEntry->d_name[0] != '.') { // if the entry don't start with a dot (so hidden dirs and hidden files)
|
|
||||||
regexReturn = regexec(®ex, vaultEntry->d_name, 0, NULL, 0);
|
|
||||||
if (!regexReturn) { // if the regex matches
|
|
||||||
altDebug("matched with the regex. It is a journal.\n");
|
|
||||||
journalsArray = realloc(journalsArray, (journalsCount + 1)*sizeof(char*)); // resize notesArray so that
|
|
||||||
journalsArray[journalsCount] = strdup(vaultEntry->d_name); // copy the dir name into notesArray
|
|
||||||
journalsCount++;
|
|
||||||
} else {
|
|
||||||
altDebug("did not matched with the regex. It is a note.\n");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
altDebug(" was ignored\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
altDebug("└ ------------------------------\n");
|
|
||||||
// free's some used memory
|
|
||||||
closedir(vaultDirectory);
|
|
||||||
*count = journalsCount; // passes the number of files
|
|
||||||
return journalsArray;
|
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-6
@@ -2,13 +2,21 @@
|
|||||||
#define NOTES_H
|
#define NOTES_H
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
char **getVaultsFromDirectory(char *dirString, size_t *count, int debug);
|
char **getJournalsFromVault(char *pathToVault, char *vault, char *journalRegex, int *count, int shouldDebug);
|
||||||
// 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
|
|
||||||
char **getNotesFromVault(char *pathToVault, char *vault, char *journalRegex, int *count, int debug);
|
|
||||||
// this function is inputed a path to a vault (which was selected before) and outpus all the suitable notes (so not the hidden ones)
|
|
||||||
// journalRegex is the regex code for the journals. If a note matches this code, it is treated as a journal and it is not outputed from this function.
|
|
||||||
char **getJournalsFromVault(char *pathToVault, char *vault, char *journalRegex, int *count, int debug);
|
|
||||||
// gets the journals from the vault
|
// gets the journals from the vault
|
||||||
// to distinguish journals from note we use regex.
|
// to distinguish journals from note we use regex.
|
||||||
// Note: we must handle them separatly as journals can either be a single file (which will treat specially) or a directory
|
// Note: we must handle them separatly as journals can either be a single file (which will treat specially) or a directory
|
||||||
|
|
||||||
|
char **getNotesFromVault(char *pathToVault, char *vault, char *journalRegex, int *count, int shouldDebug);
|
||||||
|
// this function is inputed a path to a vault (which was selected before) and outpus all the suitable notes (so not the hidden ones)
|
||||||
|
// journalRegex is the regex code for the journals. If a note matches this code, it is treated as a journal and it is not outputed from this function.
|
||||||
|
char **getVaultsFromDirectory(char *dirString, size_t *count, int shouldDebug);
|
||||||
|
// 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
|
||||||
|
char *updateJournal(char *path, char *journal, char *timeFormat, int shouldDebug);
|
||||||
|
// path is the path to the file
|
||||||
|
// journal is the name of the file
|
||||||
|
// handles both type of journal (divided and unified)
|
||||||
|
// creates new entry with date
|
||||||
|
// for divided select if we want to acces to a new entry or a old one
|
||||||
|
// returns the path to the file that needs to be opened
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+34
@@ -81,6 +81,16 @@ int doesEditorExist (char *editorToCheck, int shouldDebug) { // Some exectua
|
|||||||
return 0; // program not found
|
return 0; // program not found
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *getFormatedTime(char *format, int shouldDebug) {
|
||||||
|
debug("Inputed time format is %s", format);
|
||||||
|
time_t t = time(NULL);
|
||||||
|
struct tm *tm = localtime(&t);
|
||||||
|
char *buf = malloc(BUFFER_SIZE);
|
||||||
|
strftime(buf, BUFFER_SIZE, format, tm);
|
||||||
|
debug("Formated time is %s", buf);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
int isStringInArray(const char *string, const char **array, const int len) {
|
int isStringInArray(const char *string, const char **array, const int len) {
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
if (strcmp(string, array[i]) == 0) {
|
if (strcmp(string, array[i]) == 0) {
|
||||||
@@ -90,6 +100,30 @@ int isStringInArray(const char *string, const char **array, const int len) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int isStringInFile(const char *path, const char *string, const int shouldDebug) {
|
||||||
|
FILE *file = fopen(path, "r");
|
||||||
|
error(file == NULL, "program", "While searching for \"%s\", we could not open file %s", string, path);
|
||||||
|
char buf[BUFFER_SIZE];
|
||||||
|
|
||||||
|
while (fgets(buf, BUFFER_SIZE, file) != NULL) {
|
||||||
|
if (strstr(buf, string) != NULL) {
|
||||||
|
debug("%s contains the substring %s", buf, string);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug("The string %s is not inside %s", string, path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void appendToFile(const char *path, const char *string, const int shouldDebug) {
|
||||||
|
// (TODO LATER) we should check if it is not already at the end and not append. (Usefull for \n)
|
||||||
|
FILE *file = fopen(path, "a");
|
||||||
|
error(file == NULL, "program", "could not open %s", path);
|
||||||
|
fprintf(file, "%s", string);
|
||||||
|
fclose(file);
|
||||||
|
debug("%s was appended to %s succesfully", string, path);
|
||||||
|
}
|
||||||
|
|
||||||
void sanitize(char *string) {
|
void sanitize(char *string) {
|
||||||
for (int i = 0; i < strlen(string); i++) {
|
for (int i = 0; i < strlen(string); i++) {
|
||||||
if ((!isalnum((unsigned char)string[i]) && strchr("/\\:*?\"\'<>\n\r\t", string[i])) || ((i == 0 || i == 1) && string[i] == '.')) { // replace unwanted chars by '_'. '.' is replaced if it is only the first two chars
|
if ((!isalnum((unsigned char)string[i]) && strchr("/\\:*?\"\'<>\n\r\t", string[i])) || ((i == 0 || i == 1) && string[i] == '.')) { // replace unwanted chars by '_'. '.' is replaced if it is only the first two chars
|
||||||
|
|||||||
+11
@@ -16,6 +16,8 @@
|
|||||||
#include <cjson/cJSON.h>
|
#include <cjson/cJSON.h>
|
||||||
#include <regex.h>
|
#include <regex.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <time.h>
|
||||||
|
#define BUFFER_SIZE 256 //standard buffer size.
|
||||||
#define debug(message, ...) \
|
#define debug(message, ...) \
|
||||||
_debug(shouldDebug, __FILE__, __LINE__, __func__, message, ##__VA_ARGS__)
|
_debug(shouldDebug, __FILE__, __LINE__, __func__, message, ##__VA_ARGS__)
|
||||||
#define altDebug(message, ...) \
|
#define altDebug(message, ...) \
|
||||||
@@ -27,6 +29,7 @@
|
|||||||
extern const char *supportedEditor[]; // array of supported editors
|
extern const char *supportedEditor[]; // array of supported editors
|
||||||
extern const int numEditors; // number of supported editors
|
extern const int numEditors; // number of supported editors
|
||||||
|
|
||||||
|
//(TODO LATER) organise this mess
|
||||||
int compareString(const void *a, const void *b);
|
int compareString(const void *a, const void *b);
|
||||||
//compares two strings alphabetically.
|
//compares two strings alphabetically.
|
||||||
//this function is used for qsort
|
//this function is used for qsort
|
||||||
@@ -44,6 +47,10 @@ int isStringInArray(const char *string, const char **array, const int len);
|
|||||||
// Returns 1 if the string is in the array
|
// Returns 1 if the string is in the array
|
||||||
// Returns 0 if the string is not in the array
|
// Returns 0 if the string is not in the array
|
||||||
// If you want to only check the first n elements of the array, pass n as len
|
// If you want to only check the first n elements of the array, pass n as len
|
||||||
|
int isStringInFile(const char *path, const char *string, const int shouldDebug);
|
||||||
|
// returns 1 if the string is in the file
|
||||||
|
// returns 0 if the string is not in the file
|
||||||
|
void appendToFile(const char *path, const char *string, const int shouldDebug);
|
||||||
void sanitize(char *string);
|
void sanitize(char *string);
|
||||||
// replace unwanted chars by '_'. '.' is replaced if it is only the first two chars
|
// replace unwanted chars by '_'. '.' is replaced if it is only the first two chars
|
||||||
int rmrf(char *path);
|
int rmrf(char *path);
|
||||||
@@ -54,4 +61,8 @@ int openEditor(char *path, char *editor, int render, int endOfFile, int debug);
|
|||||||
// render: if we render the .md file with Vivify
|
// render: if we render the .md file with Vivify
|
||||||
// endOfFile: if we put the cursor at the end of the file when opening
|
// endOfFile: if we put the cursor at the end of the file when opening
|
||||||
// The program resumes when the editor is closed
|
// The program resumes when the editor is closed
|
||||||
|
char *getFormatedTime(char *format, int shouldDebug);
|
||||||
|
// see https://pubs.opengroup.org/onlinepubs/7908799/xsh/strftime.html? for formats
|
||||||
|
// returns a string (buffered at 256 chars)
|
||||||
|
// you should not forgot to free this string as it is in the heap
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user