mirror of
https://github.com/tomasriveral/NoteWrapper.git
synced 2026-08-11 18:18:36 +02:00
+1
-1
@@ -1,3 +1,3 @@
|
||||
BasedOnStyle: LLVM
|
||||
IndentWidth: 4
|
||||
ColumnLimit: 100
|
||||
ColumnLimit: 210
|
||||
|
||||
+70
-125
@@ -88,9 +88,7 @@ int main(int argc, char *argv[]) {
|
||||
free(data);
|
||||
fclose(f);
|
||||
}
|
||||
error(readBytes != size, "program",
|
||||
"Failed to read config file (%s) (%zu bytes read, expected %ld)", configPath, readBytes,
|
||||
size);
|
||||
error(readBytes != size, "program", "Failed to read config file (%s) (%zu bytes read, expected %ld)", configPath, readBytes, size);
|
||||
data[size] = '\0';
|
||||
fclose(f);
|
||||
|
||||
@@ -105,8 +103,7 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
// Parse all of the directories which will( or do) contain the vaults
|
||||
cJSON *dirJson = cJSON_GetObjectItem(json, "directory");
|
||||
error(dirJson && !cJSON_IsArray(dirJson), "user",
|
||||
"In %s, \"directory\" is missing or isn't an array", configPath);
|
||||
error(dirJson && !cJSON_IsArray(dirJson), "user", "In %s, \"directory\" is missing or isn't an array", configPath);
|
||||
int numDirectories = cJSON_GetArraySize(dirJson);
|
||||
debug("In %s, detected %d paths in \"directory\"", configPath, numDirectories);
|
||||
error(numDirectories == 0, "user", "In %s, \"directory\" is an empty array.", configPath);
|
||||
@@ -115,9 +112,8 @@ int main(int argc, char *argv[]) {
|
||||
debug("Directories:");
|
||||
cJSON *tempEntry = NULL;
|
||||
int i = 0;
|
||||
cJSON_ArrayForEach(
|
||||
tempEntry,
|
||||
dirJson) { // iterate over all the elements of the array _i. e._ over all the dirs
|
||||
cJSON_ArrayForEach(tempEntry,
|
||||
dirJson) { // iterate over all the elements of the array _i. e._ over all the dirs
|
||||
if (tempEntry && cJSON_IsString(tempEntry)) {
|
||||
if (cJSON_GetStringValue(tempEntry)[0] == '~') { // we must expand ~
|
||||
char *tempUnFixedName = cJSON_GetStringValue(tempEntry);
|
||||
@@ -130,8 +126,7 @@ int main(int argc, char *argv[]) {
|
||||
altDebug("%s\n", directoriesArray[i]);
|
||||
}
|
||||
} else {
|
||||
error(1, "user", "In %s, in \"directory\", invalid type of one of the entries.",
|
||||
configPath);
|
||||
error(1, "user", "In %s, in \"directory\", invalid type of one of the entries.", configPath);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
@@ -159,13 +154,11 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
char *editorToOpen = getenv("EDITOR"); // default to $EDITOR
|
||||
int defaultEditor =
|
||||
1; // this will be used in the warning if the editor does not exists or is unsupported.
|
||||
int defaultEditor = 1; // this will be used in the warning if the editor does not exists or is unsupported.
|
||||
cJSON *editorToOpenJSON = cJSON_GetObjectItem(json, "editor");
|
||||
if (editorToOpenJSON && cJSON_IsString(editorToOpenJSON)) {
|
||||
editorToOpen = strdup(cJSON_GetStringValue(
|
||||
editorToOpenJSON)); // we must strdup and not just = as we will free all the json after
|
||||
// (before parsing args)
|
||||
editorToOpen = strdup(cJSON_GetStringValue(editorToOpenJSON)); // we must strdup and not just = as we will free all the json after
|
||||
// (before parsing args)
|
||||
defaultEditor = 0;
|
||||
debug("In %s, \"editor\" was set to %s.", configPath, editorToOpen);
|
||||
// error(!isStringInArray(editorToOpen, supportedEditor, numEditors), "user", "%s (fetched
|
||||
@@ -194,15 +187,12 @@ int main(int argc, char *argv[]) {
|
||||
timeFormat = strdup(cJSON_GetStringValue(timeFormatJSON));
|
||||
debug("In %s, \"dateEntry\" was set to %s.", configPath, timeFormat);
|
||||
} else {
|
||||
debug(
|
||||
"In %s, \"dateEntry\" wasn't set or we encountered a abnormal type. Defaulting to %s.",
|
||||
configPath, timeFormat);
|
||||
debug("In %s, \"dateEntry\" wasn't set or we encountered a abnormal type. Defaulting to %s.", configPath, timeFormat);
|
||||
}
|
||||
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));
|
||||
debug("The value for newLineOnOpening in config.json is %d", cJSON_IsTrue(newLineOnOpeningJSON));
|
||||
|
||||
newLineOnOpening = cJSON_IsTrue(newLineOnOpeningJSON) ? 1 : 0;
|
||||
debug("In %s, \"newLineOnOpening\" was set to %d.", configPath, newLineOnOpening);
|
||||
@@ -213,8 +203,7 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
int doesBackup = 0;
|
||||
int interval =
|
||||
0; // this is an int. But some times it will be inputed a string. We must translate it.
|
||||
int interval = 0; // this is an int. But some times it will be inputed a string. We must translate it.
|
||||
// to handle linking each directory to its backup path. We create an array of char*. If we want
|
||||
// to backup the ith directory, the ith pointer will point to the path. Else, we set the ith
|
||||
// pointer to NULL.
|
||||
@@ -236,9 +225,7 @@ int main(int argc, char *argv[]) {
|
||||
cJSON *pathToBackupJSON = cJSON_GetObjectItem(backupJSON, "directory");
|
||||
debug("%s", cJSON_Print(pathToBackupJSON));
|
||||
error(pathToBackupJSON == NULL &&
|
||||
!(cJSON_IsObject(pathToBackupJSON) || cJSON_IsArray(pathToBackupJSON) ||
|
||||
cJSON_IsString(pathToBackupJSON) || cJSON_IsNumber(pathToBackupJSON) ||
|
||||
cJSON_IsBool(pathToBackupJSON)),
|
||||
!(cJSON_IsObject(pathToBackupJSON) || cJSON_IsArray(pathToBackupJSON) || cJSON_IsString(pathToBackupJSON) || cJSON_IsNumber(pathToBackupJSON) || cJSON_IsBool(pathToBackupJSON)),
|
||||
"user", "In %s, incorrect type for \"directory\". It must be a JSON object.",
|
||||
configPath); // for some reason cJSON_IsObject does not work. So we must do it
|
||||
// like this.
|
||||
@@ -247,13 +234,11 @@ int main(int argc, char *argv[]) {
|
||||
// we must iterate over the json entries
|
||||
cJSON *directoryEntry = NULL;
|
||||
int i = 0;
|
||||
cJSON_ArrayForEach(
|
||||
directoryEntry,
|
||||
dirJson) { // iterate over all the elements of the array _i. e._ over all the dirs
|
||||
cJSON_ArrayForEach(directoryEntry,
|
||||
dirJson) { // iterate over all the elements of the array _i. e._ over all the dirs
|
||||
// we don't need to type error handle as we did it before
|
||||
char *directoryEntryPath = cJSON_GetStringValue(directoryEntry);
|
||||
cJSON *pathToBackupForIthDirectoryJSON =
|
||||
cJSON_GetObjectItem(pathToBackupJSON, directoryEntryPath);
|
||||
cJSON *pathToBackupForIthDirectoryJSON = cJSON_GetObjectItem(pathToBackupJSON, directoryEntryPath);
|
||||
if (pathToBackupForIthDirectoryJSON) { // if the entry exist
|
||||
char *textPath = cJSON_GetStringValue(pathToBackupForIthDirectoryJSON);
|
||||
if (textPath[0] == '~') {
|
||||
@@ -264,8 +249,7 @@ int main(int argc, char *argv[]) {
|
||||
} else {
|
||||
backupDirectoriesArray[i] = strdup(textPath);
|
||||
}
|
||||
debug("%s will be backed up to %s", directoriesArray[i],
|
||||
backupDirectoriesArray[i]);
|
||||
debug("%s will be backed up to %s", directoriesArray[i], backupDirectoriesArray[i]);
|
||||
} else { // we set it to NULL to be sure we won't backup it
|
||||
backupDirectoriesArray[i] = NULL;
|
||||
debug("%s won't be backed up", directoriesArray[i]);
|
||||
@@ -276,8 +260,7 @@ int main(int argc, char *argv[]) {
|
||||
// handles the interval of backup
|
||||
cJSON *intervalJSON = cJSON_GetObjectItem(backupJSON, "interval");
|
||||
if (intervalJSON && cJSON_IsString(intervalJSON)) {
|
||||
char *temp = cJSON_GetStringValue(
|
||||
intervalJSON); // se comment higher. temp will be freed when calling free(json)
|
||||
char *temp = cJSON_GetStringValue(intervalJSON); // se comment higher. temp will be freed when calling free(json)
|
||||
if (strcmp(temp, "daily") == 0) {
|
||||
interval = DAILY;
|
||||
debug("interval in %s is set to \"daily\" which is %d", configPath, DAILY);
|
||||
@@ -321,8 +304,7 @@ int main(int argc, char *argv[]) {
|
||||
rsyncArgs[i] = strdup(cJSON_GetStringValue(argJSON));
|
||||
altDebug("%s\n", rsyncArgs[i]);
|
||||
} else {
|
||||
error(1, "user", "One element in rsyncArgs array in %s is not a string",
|
||||
configPath);
|
||||
error(1, "user", "One element in rsyncArgs array in %s is not a string", configPath);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -407,8 +389,7 @@ backup_config_end:
|
||||
printf("Options:\n");
|
||||
printf(" -c, --config <path/to/config> Specify the config file.\n");
|
||||
printf(" -h, --help Display this message.\n");
|
||||
printf(
|
||||
" -e, --editor Specify the editor to open.\n");
|
||||
printf(" -e, --editor Specify the editor to open.\n");
|
||||
printf(" -j, --jump Jumps to the end of the file "
|
||||
"on opening.\n");
|
||||
printf(" -J, --no-jump Do not jump to the end of "
|
||||
@@ -468,8 +449,7 @@ backup_config_end:
|
||||
case 'h':
|
||||
printf("Usage: notewrapper [options]\n");
|
||||
printf("Options:\n");
|
||||
printf(
|
||||
" -c, --config <path/to/config> Specify the config file.\n");
|
||||
printf(" -c, --config <path/to/config> Specify the config file.\n");
|
||||
printf(" -h, --help Display this message.\n");
|
||||
printf(" -e, --editor Specify the editor to "
|
||||
"open.\n");
|
||||
@@ -485,8 +465,7 @@ backup_config_end:
|
||||
printf(" -v, --vault <vault's name> Specify the vault.\n");
|
||||
printf(" --version Display the program "
|
||||
"version and the GPL3 notice.\n");
|
||||
printf(
|
||||
" -V, --verbose Show debug information.\n");
|
||||
printf(" -V, --verbose Show debug information.\n");
|
||||
return 0;
|
||||
|
||||
// -------- flags with arguments (MUST be last in group) --------
|
||||
@@ -495,8 +474,7 @@ backup_config_end:
|
||||
case 'v':
|
||||
case 'c': {
|
||||
|
||||
error(arg[j + 1] != '\0', "user", "-%c must not be combined with other flags",
|
||||
opt);
|
||||
error(arg[j + 1] != '\0', "user", "-%c must not be combined with other flags", opt);
|
||||
|
||||
error(i + 1 == argc, "user", "Missing argument for -%c", opt);
|
||||
|
||||
@@ -553,8 +531,7 @@ backup_config_end:
|
||||
|
||||
if (doesBackup) {
|
||||
debug("Handling backup");
|
||||
handleBackups(directoriesArray, numDirectories, backupDirectoriesArray, homedir, interval,
|
||||
(const char **)rsyncArgs, rsyncArgsNumber, shouldDebug);
|
||||
handleBackups(directoriesArray, numDirectories, backupDirectoriesArray, homedir, interval, (const char **)rsyncArgs, rsyncArgsNumber, shouldDebug);
|
||||
}
|
||||
|
||||
initscr(); // initialize ncurses
|
||||
@@ -567,10 +544,9 @@ backup_config_end:
|
||||
|
||||
int vaultsCount = 0;
|
||||
int *vaultsCountForEachDirectory = malloc(numDirectories * sizeof(int));
|
||||
char **vaultsArray = getVaultsFromDirectories(
|
||||
directoriesArray, numDirectories, vaultsCountForEachDirectory, &vaultsCount,
|
||||
shouldDebug); // when selecting each vault won't show the directory from which they
|
||||
// come. We will find this later.
|
||||
char **vaultsArray = getVaultsFromDirectories(directoriesArray, numDirectories, vaultsCountForEachDirectory, &vaultsCount,
|
||||
shouldDebug); // when selecting each vault won't show the directory from which they
|
||||
// come. We will find this later.
|
||||
|
||||
// bypass if -v or --vault is set
|
||||
if (bypassSelectionVault) {
|
||||
@@ -578,10 +554,9 @@ backup_config_end:
|
||||
// create a new one
|
||||
vaultSelected = bypassSelectionVaultValue;
|
||||
debug("bypassing vault selection");
|
||||
if (!isStringInArray(
|
||||
bypassSelectionVaultValue, (const char **)vaultsArray,
|
||||
vaultsCount)) { // we pass just vaultsCount and not vaultsCount + extraOptions
|
||||
// to avoid matching with the extraOptions.
|
||||
if (!isStringInArray(bypassSelectionVaultValue, (const char **)vaultsArray,
|
||||
vaultsCount)) { // we pass just vaultsCount and not vaultsCount + extraOptions
|
||||
// to avoid matching with the extraOptions.
|
||||
debug("[BYPASS] %s did not exist. Creating a new vault");
|
||||
goto vault_creation;
|
||||
} else {
|
||||
@@ -600,49 +575,39 @@ backup_config_end:
|
||||
|
||||
// adds "create a new vault" into the vaultsArray
|
||||
const int extraOptions = 3;
|
||||
vaultsArray =
|
||||
realloc(vaultsArray, (vaultsCount + extraOptions) *
|
||||
sizeof(char *)); // resize vaultsArray to fit the extra options
|
||||
vaultsArray[vaultsCount] = "Create a new vault"; // some more options that are not vaults
|
||||
vaultsArray = realloc(vaultsArray, (vaultsCount + extraOptions) * sizeof(char *)); // resize vaultsArray to fit the extra options
|
||||
vaultsArray[vaultsCount] = "Create a new vault"; // some more options that are not vaults
|
||||
vaultsArray[vaultsCount + 1] = "Settings";
|
||||
vaultsArray[vaultsCount + 2] = "Quit (Ctrl+C)";
|
||||
|
||||
vaultSelected = ncursesSelect(
|
||||
vaultsArray, "Select vault to open (Use arrows or WASD, Enter to select):", vaultsCount,
|
||||
extraOptions, " ", "Or select an option below", "", shouldDebug);
|
||||
vaultSelected = ncursesSelect(vaultsArray, "Select vault to open (Use arrows or WASD, Enter to select):", vaultsCount, extraOptions, " ", "Or select an option below", "", shouldDebug);
|
||||
|
||||
// now that we won't use vaultsArray in this iteration of the loop, we should free it and
|
||||
// all its elements. (As this is memory in the heap and not the stack and thus is our
|
||||
// responsability to manage)
|
||||
for (int i = 0; i < vaultsCount; i++) {
|
||||
if (vaultSelected !=
|
||||
vaultsArray[i]) { // i forgot this condition before. and freed the pointer equal to
|
||||
// vaultSelected... So don't remove this condition
|
||||
free(vaultsArray[i]); // we must only free the vaults options and not the
|
||||
// extraOptions to avoid segfault
|
||||
if (vaultSelected != vaultsArray[i]) { // i forgot this condition before. and freed the pointer equal to
|
||||
// vaultSelected... So don't remove this condition
|
||||
free(vaultsArray[i]); // we must only free the vaults options and not the
|
||||
// extraOptions to avoid segfault
|
||||
}
|
||||
}
|
||||
|
||||
debug("Selected vault: %s", vaultSelected);
|
||||
if (strcmp(vaultSelected, "Create a new vault") != 0 &&
|
||||
strcmp(vaultSelected, "Settings") != 0 && strcmp(vaultSelected, "Quit (Ctrl+C)") != 0) {
|
||||
if (strcmp(vaultSelected, "Create a new vault") != 0 && strcmp(vaultSelected, "Settings") != 0 && strcmp(vaultSelected, "Quit (Ctrl+C)") != 0) {
|
||||
note_selection:
|
||||
bypassSelectionVault = 0; // we must reset bypassSelectionVault to not get stuck in a
|
||||
// infinite loop of bypassing
|
||||
int shouldChangeVault = 0;
|
||||
// we must find the directory from which the vault comes again.
|
||||
char *notesDirectoryString = getDirectoryFromVault(
|
||||
vaultSelected, vaultsArray, vaultsCount, vaultsCountForEachDirectory,
|
||||
directoriesArray, numDirectories, shouldDebug);
|
||||
char *notesDirectoryString = getDirectoryFromVault(vaultSelected, vaultsArray, vaultsCount, vaultsCountForEachDirectory, directoriesArray, numDirectories, shouldDebug);
|
||||
while (!shouldExit && !shouldChangeVault) {
|
||||
// this loop is the note selector
|
||||
int filesCount = 0;
|
||||
char **filesArray = getNotesFromVault(notesDirectoryString, vaultSelected,
|
||||
journalRegex, &filesCount, shouldDebug);
|
||||
char **filesArray = getNotesFromVault(notesDirectoryString, vaultSelected, journalRegex, &filesCount, shouldDebug);
|
||||
|
||||
int journalCount = 0;
|
||||
char **journalArray = getJournalsFromVault(
|
||||
notesDirectoryString, vaultSelected, journalRegex, &journalCount, shouldDebug);
|
||||
char **journalArray = getJournalsFromVault(notesDirectoryString, vaultSelected, journalRegex, &journalCount, shouldDebug);
|
||||
|
||||
// appends the journal at the end of filesArray
|
||||
filesArray = realloc(filesArray, (filesCount + journalCount) * sizeof(char *));
|
||||
@@ -661,9 +626,7 @@ backup_config_end:
|
||||
}
|
||||
// adds options
|
||||
int extraNotesOptions = 4;
|
||||
filesArray = realloc(
|
||||
filesArray, (filesCount + extraNotesOptions) *
|
||||
sizeof(char *)); // resize filesArray to fit the extra options
|
||||
filesArray = realloc(filesArray, (filesCount + extraNotesOptions) * sizeof(char *)); // resize filesArray to fit the extra options
|
||||
filesArray[filesCount] = "Create new note";
|
||||
filesArray[filesCount + 1] = "Back to vault selection";
|
||||
filesArray[filesCount + 2] = "Delete vault";
|
||||
@@ -673,10 +636,9 @@ backup_config_end:
|
||||
if (bypassSelectionNote) {
|
||||
debug("We are bypassing note selection.");
|
||||
noteSelected = bypassSelectionNoteValue;
|
||||
if (isStringInArray(
|
||||
noteSelected, (const char **)filesArray,
|
||||
filesCount)) { // we just give filesCount and not filesCount +
|
||||
// extraOptions to avoid matching with an extra options.
|
||||
if (isStringInArray(noteSelected, (const char **)filesArray,
|
||||
filesCount)) { // we just give filesCount and not filesCount +
|
||||
// extraOptions to avoid matching with an extra options.
|
||||
debug("The note specified with -n or --note does exist. Opening it.");
|
||||
goto open_note;
|
||||
} else { // if the specified note doesn't exist. We creat it
|
||||
@@ -684,34 +646,27 @@ backup_config_end:
|
||||
goto note_creation;
|
||||
}
|
||||
}
|
||||
noteSelected = ncursesSelect(
|
||||
filesArray,
|
||||
"Select note or journal to open (Use arrows or WASD, Enter to select):",
|
||||
filesCount, extraNotesOptions, " ", "Or select an option below", "",
|
||||
shouldDebug);
|
||||
noteSelected =
|
||||
ncursesSelect(filesArray, "Select note or journal to open (Use arrows or WASD, Enter to select):", filesCount, extraNotesOptions, " ", "Or select an option below", "", shouldDebug);
|
||||
// now that we won't use filesArray in this iteration of the loop, we should free it
|
||||
// and all its elements. (As this is memory in the heap and not the stack and thus
|
||||
// is our responsability to manage)
|
||||
for (int i = 0; i < filesCount; i++) {
|
||||
if (noteSelected != filesArray[i]) { // we must prevent noteSelected to be
|
||||
// freed. It will cause a lot of problems
|
||||
free(filesArray[i]); // we must only free the files options and not the
|
||||
// extraOptions to avoid segfault
|
||||
free(filesArray[i]); // we must only free the files options and not the
|
||||
// extraOptions to avoid segfault
|
||||
}
|
||||
}
|
||||
free(filesArray);
|
||||
debug("Selected note: %s", noteSelected);
|
||||
if (strcmp(noteSelected, "Create new note") != 0 &&
|
||||
strcmp(noteSelected, "Back to vault selection") != 0 &&
|
||||
strcmp(noteSelected, "Delete vault") != 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:
|
||||
bypassSelectionNote =
|
||||
0; // we must reset bypassSelectionNote to avoid getting into an infinite
|
||||
// loop of bypassing the note selection
|
||||
bypassSelectionNote = 0; // we must reset bypassSelectionNote to avoid getting into an infinite
|
||||
// loop of bypassing the note selection
|
||||
char *fullPath = malloc(PATH_MAX);
|
||||
snprintf(fullPath, PATH_MAX, "%s/%s/%s", notesDirectoryString, vaultSelected,
|
||||
noteSelected);
|
||||
snprintf(fullPath, PATH_MAX, "%s/%s/%s", notesDirectoryString, vaultSelected, noteSelected);
|
||||
// if it is a journal we must update it before
|
||||
regex_t regex;
|
||||
int regexReturn = regcomp(®ex, journalRegex, 0);
|
||||
@@ -722,19 +677,17 @@ backup_config_end:
|
||||
*journalWasUpdated = 0;
|
||||
if (!regexReturn) { // if the regex matches -> it's a journal
|
||||
debug("%s is a journal. Updating it...", noteSelected);
|
||||
fullPath = updateJournal(
|
||||
fullPath, noteSelected, timeFormat, journalWasUpdated,
|
||||
shouldDebug); // we return the path. As if it is a divided journal we
|
||||
// must point to the correct entry
|
||||
fullPath = updateJournal(fullPath, noteSelected, timeFormat, journalWasUpdated,
|
||||
shouldDebug); // we return the path. As if it is a divided journal we
|
||||
// must point to the correct entry
|
||||
}
|
||||
if (newLineOnOpening) {
|
||||
if (*journalWasUpdated) {
|
||||
appendToFile(
|
||||
fullPath, " \n",
|
||||
shouldDebug); // when updating the journal it adds a \n char at the
|
||||
// end. So appendToFile(\n) does not work. We append a
|
||||
// (special and rare) whitespace character + \n to
|
||||
// bypass this issue.
|
||||
appendToFile(fullPath, " \n",
|
||||
shouldDebug); // when updating the journal it adds a \n char at the
|
||||
// end. So appendToFile(\n) does not work. We append a
|
||||
// (special and rare) whitespace character + \n to
|
||||
// bypass this issue.
|
||||
}
|
||||
appendToFile(fullPath, "\n", shouldDebug);
|
||||
}
|
||||
@@ -742,30 +695,24 @@ backup_config_end:
|
||||
free(fullPath);
|
||||
} else if (strcmp(noteSelected, "Create new note") == 0) {
|
||||
note_creation:
|
||||
noteSelected =
|
||||
createNewNote(notesDirectoryString, vaultSelected, bypassSelectionNote,
|
||||
bypassSelectionNoteValue, journalRegex, shouldDebug);
|
||||
noteSelected = createNewNote(notesDirectoryString, vaultSelected, bypassSelectionNote, bypassSelectionNoteValue, journalRegex, shouldDebug);
|
||||
// we can just go back to open_note
|
||||
goto open_note;
|
||||
} else if (strcmp(noteSelected, "Back to vault selection") == 0) {
|
||||
shouldChangeVault = 1;
|
||||
} else if (strcmp(noteSelected, "Delete vault") == 0) {
|
||||
// we must find where does the vault comes from.
|
||||
char *notesDirectoryString = getDirectoryFromVault(
|
||||
vaultSelected, vaultsArray, vaultsCount, vaultsCountForEachDirectory,
|
||||
directoriesArray, numDirectories, shouldDebug);
|
||||
char *notesDirectoryString = getDirectoryFromVault(vaultSelected, vaultsArray, vaultsCount, vaultsCountForEachDirectory, directoriesArray, numDirectories, shouldDebug);
|
||||
const char *yesNo[] = {"No, go back to note selection.", "Yes."};
|
||||
char *answer =
|
||||
ncursesSelect((char **)yesNo,
|
||||
"Are you sure you want to delete the entire vault? This can "
|
||||
"not be undone (Use arrows or WASD, Enter to select):",
|
||||
1, 1, " ", "", "", shouldDebug);
|
||||
char *answer = ncursesSelect((char **)yesNo,
|
||||
"Are you sure you want to delete the entire vault? This can "
|
||||
"not be undone (Use arrows or WASD, Enter to select):",
|
||||
1, 1, " ", "", "", shouldDebug);
|
||||
debug("You answered: %s for deleting the vault %s", answer, vaultSelected);
|
||||
if (strcmp(answer, "Yes.") == 0) {
|
||||
// delete the vault after confirmation by the user
|
||||
char pathToRMRF[PATH_MAX];
|
||||
snprintf(pathToRMRF, PATH_MAX, "%s/%s", notesDirectoryString,
|
||||
vaultSelected);
|
||||
snprintf(pathToRMRF, PATH_MAX, "%s/%s", notesDirectoryString, vaultSelected);
|
||||
debug("Removed the directory: %s", pathToRMRF);
|
||||
rmrf(pathToRMRF, shouldDebug);
|
||||
shouldChangeVault = 1;
|
||||
@@ -778,14 +725,12 @@ backup_config_end:
|
||||
free(vaultsArray);
|
||||
} else if (strcmp(vaultSelected, "Create a new vault") == 0) {
|
||||
vault_creation:
|
||||
createNewVault(directoriesArray, numDirectories, vaultsArray, vaultsCount,
|
||||
bypassSelectionVault, bypassSelectionVaultValue, shouldDebug);
|
||||
createNewVault(directoriesArray, numDirectories, vaultsArray, vaultsCount, bypassSelectionVault, bypassSelectionVaultValue, shouldDebug);
|
||||
bypassSelectionVault = 0; // we need to reset bypassSelectionVault to avoid getting into
|
||||
// an infinite loop of bypassing
|
||||
} else if (strcmp(vaultSelected, "Settings") == 0) {
|
||||
openEditor(
|
||||
configPath, editorToOpen, 0, 0,
|
||||
shouldDebug); // as this is not a md file we set render and jumptoEnfOfFile to 0
|
||||
openEditor(configPath, editorToOpen, 0, 0,
|
||||
shouldDebug); // as this is not a md file we set render and jumptoEnfOfFile to 0
|
||||
} else if (strcmp(vaultSelected, "Quit (Ctrl+C)") == 0) {
|
||||
debug("The program was exited");
|
||||
shouldExit = 1;
|
||||
|
||||
+48
-88
@@ -1,9 +1,7 @@
|
||||
#include "notes.h"
|
||||
#include "utils.h"
|
||||
|
||||
char *getDirectoryFromVault(char *targetVault, char **vaultsArray, int vaultTotalNumber,
|
||||
int *vaultNumberPerDirectory, char **directoryArray,
|
||||
int directoryNumber, int shouldDebug) {
|
||||
char *getDirectoryFromVault(char *targetVault, char **vaultsArray, int vaultTotalNumber, int *vaultNumberPerDirectory, char **directoryArray, int directoryNumber, int shouldDebug) {
|
||||
debug("Searching the vault %s inside all the directories...", targetVault);
|
||||
debug("Here are how many vaults there is per directory:");
|
||||
for (int i = 0; i < directoryNumber; i++) {
|
||||
@@ -29,8 +27,7 @@ char *getDirectoryFromVault(char *targetVault, char **vaultsArray, int vaultTota
|
||||
"Such person would be a terrible monster... One must imagine GCC and clangd happy.";
|
||||
}
|
||||
|
||||
char **getJournalsFromVault(char *pathToVault, char *vault, char *journalRegex, int *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/
|
||||
@@ -41,34 +38,27 @@ char **getJournalsFromVault(char *pathToVault, char *vault, char *journalRegex,
|
||||
DIR *vaultDirectory = opendir(tempPath);
|
||||
error(vaultDirectory == NULL, "program", "Could not open directory %s", tempPath);
|
||||
char **journalsArray = NULL; // will contain all the notes
|
||||
int journalsCount =
|
||||
0; // we need to count how many notes there is to always readjust how many memory we alloc
|
||||
int 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");
|
||||
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)
|
||||
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)
|
||||
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
|
||||
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");
|
||||
@@ -84,8 +74,7 @@ char **getJournalsFromVault(char *pathToVault, char *vault, char *journalRegex,
|
||||
return journalsArray;
|
||||
}
|
||||
|
||||
char **getNotesFromVault(char *pathToVault, char *vault, char *journalRegex, int *count,
|
||||
int shouldDebug) {
|
||||
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) originally from
|
||||
// https://www.geeksforgeeks.org/c/c-program-list-files-sub-directories-directory/
|
||||
@@ -97,8 +86,7 @@ char **getNotesFromVault(char *pathToVault, char *vault, char *journalRegex, int
|
||||
DIR *vaultDirectory = opendir(tempPath);
|
||||
error(vaultDirectory == NULL, "program", "Could not open directory %s", tempPath);
|
||||
char **notesArray = NULL; // will contain all the notes
|
||||
int notesCount =
|
||||
0; // we need to count how many notes there is to always readjust how many memory we alloc
|
||||
int 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:");
|
||||
@@ -111,22 +99,18 @@ char **getNotesFromVault(char *pathToVault, char *vault, char *journalRegex, int
|
||||
int regexReturn;
|
||||
// compiles the regex
|
||||
regexReturn = regcomp(®ex, journalRegex, 0);
|
||||
if (entryName[0] !=
|
||||
'.') { // if the entry don't start with a dot (so hidden dirs and hidden files)
|
||||
if (entryName[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,
|
||||
entryName); // sets the full absolute path to fullPathEntry
|
||||
// check if it matches the regex. If it does not match regexReturn != 0.
|
||||
regexReturn = regexec(®ex, entryName, 0, NULL, 0);
|
||||
struct stat metadataPathEntry;
|
||||
if (stat(fullPathEntry, &metadataPathEntry) == 0 && entryName[entryLenght - 3] == '.' &&
|
||||
entryName[entryLenght - 2] == 'm' && entryName[entryLenght - 1] == 'd' &&
|
||||
regexReturn &&
|
||||
S_ISREG(metadataPathEntry.st_mode)) { // if this entry is a file ending in .md and
|
||||
// that does no match the regex
|
||||
notesArray = realloc(notesArray, (notesCount + 1) *
|
||||
sizeof(char *)); // resize notesArray so that
|
||||
notesArray[notesCount] = strdup(entryName); // copy the dir name into notesArray
|
||||
if (stat(fullPathEntry, &metadataPathEntry) == 0 && entryName[entryLenght - 3] == '.' && entryName[entryLenght - 2] == 'm' && entryName[entryLenght - 1] == 'd' && regexReturn &&
|
||||
S_ISREG(metadataPathEntry.st_mode)) { // if this entry is a file ending in .md and
|
||||
// that does no match the regex
|
||||
notesArray = realloc(notesArray, (notesCount + 1) * sizeof(char *)); // resize notesArray so that
|
||||
notesArray[notesCount] = strdup(entryName); // copy the dir name into notesArray
|
||||
notesCount++;
|
||||
altDebug("did not match with the regex. It is a note.\n");
|
||||
} else if (!regexReturn) {
|
||||
@@ -144,8 +128,7 @@ char **getNotesFromVault(char *pathToVault, char *vault, char *journalRegex, int
|
||||
return notesArray;
|
||||
}
|
||||
|
||||
char **getVaultsFromDirectories(char **directoryStringArray, int directoryNumber,
|
||||
int *vaultsPerDirectoryNumber, int *count, int shouldDebug) {
|
||||
char **getVaultsFromDirectories(char **directoryStringArray, int directoryNumber, int *vaultsPerDirectoryNumber, int *count, int shouldDebug) {
|
||||
// to avoid having to work with a tree-dimensional array. We will use a 2d and
|
||||
// vaultsPerDirectoryNumber will indicate the width of the directories.
|
||||
char **vaultsArray = NULL;
|
||||
@@ -160,8 +143,7 @@ char **getVaultsFromDirectories(char **directoryStringArray, int directoryNumber
|
||||
DIR *vaultsDirectory = opendir(directoryStringArray[i]);
|
||||
error(!vaultsDirectory, "program", "Could not open directory %s", directoryStringArray[i]);
|
||||
vaultsPerDirectoryNumber[i] = 0;
|
||||
debug("┌------------------------------\n Detected files and dirs %s:",
|
||||
directoryStringArray[i]);
|
||||
debug("┌------------------------------\n Detected files and dirs %s:", directoryStringArray[i]);
|
||||
// Refer https://pubs.opengroup.org/onlinepubs/7990989775/xsh/readdir.html
|
||||
// for readdir()
|
||||
while ((vaultsDirectoryEntry = readdir(vaultsDirectory)) != NULL) {
|
||||
@@ -174,18 +156,15 @@ char **getVaultsFromDirectories(char **directoryStringArray, int directoryNumber
|
||||
altDebug(" (%s)", tempFullEntryPath);
|
||||
// checking the metadata to see if it is a dir
|
||||
struct stat metadataEntry;
|
||||
if (stat(tempFullEntryPath, &metadataEntry) == 0 &&
|
||||
S_ISDIR(metadataEntry.st_mode)) { // get's the metadata (stat should return 0 if
|
||||
// fails) and sees if it is a dir.
|
||||
if (stat(tempFullEntryPath, &metadataEntry) == 0 && S_ISDIR(metadataEntry.st_mode)) { // get's the metadata (stat should return 0 if
|
||||
// fails) and sees if it is a dir.
|
||||
altDebug(" is a vault");
|
||||
vaultsArray =
|
||||
realloc(vaultsArray, sizeof(char *) * (nthVault + 1)); // resize vaultsArray
|
||||
vaultsArray = realloc(vaultsArray, sizeof(char *) * (nthVault + 1)); // resize vaultsArray
|
||||
error(vaultsArray == NULL, "program", "realloc failed");
|
||||
vaultsPerDirectoryNumber[i]++; // it will be used later to know which vaults
|
||||
// goes into which directory
|
||||
vaultsArray[nthVault] =
|
||||
strdup(entryName); // we use strdup and not strcpy, because memory used with
|
||||
// opendir and readdir will be closed.
|
||||
vaultsPerDirectoryNumber[i]++; // it will be used later to know which vaults
|
||||
// goes into which directory
|
||||
vaultsArray[nthVault] = strdup(entryName); // we use strdup and not strcpy, because memory used with
|
||||
// opendir and readdir will be closed.
|
||||
error(vaultsArray[nthVault] == NULL, "program", "strdup failed");
|
||||
nthVault++; // it is used immediatly to set the vault into directoryStringArray
|
||||
} else {
|
||||
@@ -209,11 +188,9 @@ char **getVaultsFromDirectories(char **directoryStringArray, int directoryNumber
|
||||
return vaultsArray;
|
||||
}
|
||||
|
||||
char *updateJournal(char *path, char *journal, char *timeFormat, int *journalWasUpdated,
|
||||
int shouldDebug) {
|
||||
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.
|
||||
char *updateJournal(char *path, char *journal, char *timeFormat, int *journalWasUpdated, int shouldDebug) {
|
||||
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 *date = getFormatedTime(timeFormat, shouldDebug);
|
||||
@@ -221,8 +198,7 @@ char *updateJournal(char *path, char *journal, char *timeFormat, int *journalWas
|
||||
char dateWithExtension[PATH_MAX];
|
||||
snprintf(dateWithExtension, PATH_MAX, "%s.md", date);
|
||||
sanitize(dateWithExtension);
|
||||
debug("Sanitized date: %s\n(it might be used later for a file name if the journal is divided)",
|
||||
dateWithExtension);
|
||||
debug("Sanitized date: %s\n(it might be used later for a file name if the journal is divided)", dateWithExtension);
|
||||
struct stat metadata;
|
||||
stat(path, &metadata);
|
||||
if (S_ISREG(metadata.st_mode)) {
|
||||
@@ -260,19 +236,15 @@ char *updateJournal(char *path, char *journal, char *timeFormat, int *journalWas
|
||||
// iterates over all the entries from the dir
|
||||
while ((dividedJournalEntry = readdir(dividedJournalDirectory)) != NULL) {
|
||||
altDebug("%s\n", dividedJournalEntry->d_name);
|
||||
if (dividedJournalEntry->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", path,
|
||||
dividedJournalEntry->d_name); // sets the full absolute path to fullPathEntry
|
||||
if (dividedJournalEntry->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", path,
|
||||
dividedJournalEntry->d_name); // sets the full absolute path to fullPathEntry
|
||||
|
||||
struct stat metadataPathEntry;
|
||||
if (stat(fullPathEntry, &metadataPathEntry) == 0 &&
|
||||
S_ISREG(metadataPathEntry.st_mode)) { // if this entry is a directory
|
||||
if (stat(fullPathEntry, &metadataPathEntry) == 0 && S_ISREG(metadataPathEntry.st_mode)) { // if this entry is a directory
|
||||
entryArray = realloc(entryArray, (entryCount + 1) * sizeof(char *));
|
||||
entryArray[entryCount] =
|
||||
strdup(dividedJournalEntry->d_name); // copy the dir name into entryArray
|
||||
entryArray[entryCount] = strdup(dividedJournalEntry->d_name); // copy the dir name into entryArray
|
||||
entryCount++;
|
||||
}
|
||||
}
|
||||
@@ -287,19 +259,14 @@ char *updateJournal(char *path, char *journal, char *timeFormat, int *journalWas
|
||||
// element
|
||||
|
||||
// we must now select to create new entry or to enter in old one
|
||||
char *selectedOption = ncursesSelect(
|
||||
entryArray,
|
||||
"Create new entry or acces old entry (Use arrows or WASD, Enter to select):",
|
||||
extraOptions, entryCount - extraOptions, " ", " ", "",
|
||||
shouldDebug); // the "Create new entry for the journal %s" will be the only options. All
|
||||
// other will be extraOptions. This is made so that "Create [...] %s" will
|
||||
// always be on top
|
||||
char *selectedOption = ncursesSelect(entryArray, "Create new entry or acces old entry (Use arrows or WASD, Enter to select):", extraOptions, entryCount - extraOptions, " ", " ", "",
|
||||
shouldDebug); // the "Create new entry for the journal %s" will be the only options. All
|
||||
// other will be extraOptions. This is made so that "Create [...] %s" will
|
||||
// always be on top
|
||||
debug("Selected option from journal entry selection: %s", selectedOption);
|
||||
if (strcmp(selectedOption, createEntryMessage) == 0) { // create new entry
|
||||
char temp[PATH_MAX];
|
||||
error(strlen(path) + 1 + strlen(dateWithExtension) + 1 > PATH_MAX,
|
||||
"Error file path too long. %s/%s must not exceed PATH_MAX", path,
|
||||
dateWithExtension);
|
||||
error(strlen(path) + 1 + strlen(dateWithExtension) + 1 > PATH_MAX, "Error file path too long. %s/%s must not exceed PATH_MAX", path, dateWithExtension);
|
||||
snprintf(temp, PATH_MAX, "%s/%s", path, dateWithExtension);
|
||||
strncpy(path, temp, PATH_MAX);
|
||||
if (!isStringInArray(dateWithExtension, (const char **)entryArray,
|
||||
@@ -315,19 +282,13 @@ char *updateJournal(char *path, char *journal, char *timeFormat, int *journalWas
|
||||
free(createEntryMessage);
|
||||
*journalWasUpdated = 1;
|
||||
} else {
|
||||
debug("Today's entry (%s) already exist. We won't create a new one.",
|
||||
dateWithExtension);
|
||||
debug("Today's entry (%s) already exist. We won't create a new one.", dateWithExtension);
|
||||
}
|
||||
} else if (strcmp(selectedOption, entryArray[1]) ==
|
||||
0) { // if we choosed to open a random entry
|
||||
} else if (strcmp(selectedOption, entryArray[1]) == 0) { // if we choosed to open a random entry
|
||||
// setting up the seed for rand()
|
||||
srand(time(NULL)); // not totaly random, just pseudorandom
|
||||
int randomEntry =
|
||||
extraOptions +
|
||||
(rand() %
|
||||
(entryCount -
|
||||
extraOptions)); // we get a random number between extraOptions and entryCount (so
|
||||
// all journal entries and not extraOptions)
|
||||
srand(time(NULL)); // not totaly random, just pseudorandom
|
||||
int randomEntry = extraOptions + (rand() % (entryCount - extraOptions)); // we get a random number between extraOptions and entryCount (so
|
||||
// all journal entries and not extraOptions)
|
||||
char temp[PATH_MAX];
|
||||
snprintf(temp, PATH_MAX, "%s/%s", path,
|
||||
entryArray[randomEntry]); // reconstruct the path
|
||||
@@ -335,9 +296,8 @@ char *updateJournal(char *path, char *journal, char *timeFormat, int *journalWas
|
||||
debug("Selected random entry %s. It's path is %s.", entryArray[randomEntry], path);
|
||||
} else if (strcmp(selectedOption, entryArray[2]) == 0) { // if we choosed to search
|
||||
char *temp = fzfSelect(path, "Input text to be searched",
|
||||
shouldDebug); // uses ripgrep and fzf to search inside the files
|
||||
char *selectedOption =
|
||||
malloc(PATH_MAX); // we can't just use path as both input and output of snprintf
|
||||
shouldDebug); // uses ripgrep and fzf to search inside the files
|
||||
char *selectedOption = malloc(PATH_MAX); // we can't just use path as both input and output of snprintf
|
||||
snprintf(selectedOption, PATH_MAX, "%s/%s", path, temp);
|
||||
path = strdup(selectedOption);
|
||||
free(selectedOption);
|
||||
|
||||
+5
-11
@@ -3,27 +3,22 @@
|
||||
#include "ui.h"
|
||||
#include "utils.h"
|
||||
// find which directory contains targetVault
|
||||
char *getDirectoryFromVault(char *targetVault, char **vaultsArray, int vaultTotalNumber,
|
||||
int *vaultNumberPerDirectory, char **directoryArray,
|
||||
int directoryNumber, int shouldDebug);
|
||||
char *getDirectoryFromVault(char *targetVault, char **vaultsArray, int vaultTotalNumber, int *vaultNumberPerDirectory, char **directoryArray, int directoryNumber, int shouldDebug);
|
||||
// gets the journals from the vault.
|
||||
// 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.
|
||||
char **getJournalsFromVault(char *pathToVault, char *vault, char *journalRegex, int *count,
|
||||
int shouldDebug);
|
||||
char **getJournalsFromVault(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 **getNotesFromVault(char *pathToVault, char *vault, char *journalRegex, int *count,
|
||||
int shouldDebug);
|
||||
char **getNotesFromVault(char *pathToVault, char *vault, char *journalRegex, int *count, int shouldDebug);
|
||||
// function gets as input an array of directoryNumber strings. Which are the directories the
|
||||
// function will search for vaults. it returns an array of vaults. the vaults are organized in order
|
||||
// per directory. vaultsPerDirectoryNumber and count should be initiallized before calling the
|
||||
// function and the address be inputed. count is the total number of vaults.
|
||||
// vaultsPerDirectoryNumber gives how many vaults each directory has.
|
||||
char **getVaultsFromDirectories(char **directoryStringArray, int directoryNumber,
|
||||
int *vaultsPerDirectoryNumber, int *count, int shouldDebug);
|
||||
char **getVaultsFromDirectories(char **directoryStringArray, int directoryNumber, int *vaultsPerDirectoryNumber, int *count, int shouldDebug);
|
||||
// path is the path to the file.
|
||||
// journal is the name of the file.
|
||||
// journalWasUpdated will be set to 1 if a new entry was created
|
||||
@@ -31,6 +26,5 @@ char **getVaultsFromDirectories(char **directoryStringArray, int directoryNumber
|
||||
// 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.
|
||||
char *updateJournal(char *path, char *journal, char *timeFormat, int *journalWasUpdated,
|
||||
int shouldDebug);
|
||||
char *updateJournal(char *path, char *journal, char *timeFormat, int *journalWasUpdated, int shouldDebug);
|
||||
#endif
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
#include "ui.h"
|
||||
#include "utils.h"
|
||||
|
||||
void createNewVault(char **directoriesArray, int directoryCount, char **vaultsArray, int vaultCount,
|
||||
int bypass, char *bypassvalue, int shouldDebug) {
|
||||
void createNewVault(char **directoriesArray, int directoryCount, char **vaultsArray, int vaultCount, int bypass, char *bypassvalue, int shouldDebug) {
|
||||
int duplicateWarning = 0; // set to 1 later if the vault you tried to create already existed
|
||||
int emptyWarning = 0; // set to 1 later if inpted empty name
|
||||
input_screen:
|
||||
// choose in which directory the vault will be created
|
||||
char *dirToVault = ncursesSelect(
|
||||
directoriesArray,
|
||||
"Select a directory, in which the vault will remain (Use arrows or WASD, Enter to select)",
|
||||
directoryCount, 0, "", "", " ", shouldDebug);
|
||||
char *dirToVault = ncursesSelect(directoriesArray, "Select a directory, in which the vault will remain (Use arrows or WASD, Enter to select)", directoryCount, 0, "", "", " ", shouldDebug);
|
||||
char *vaultName = malloc(PATH_MAX);
|
||||
if (!bypass) { // if won't bypass (if -v or --vault weren't set)
|
||||
echo();
|
||||
@@ -69,8 +65,7 @@ input_screen:
|
||||
free(vaultName);
|
||||
}
|
||||
|
||||
char *createNewNote(char dirToVault[PATH_MAX], char *vaultFromDir, int bypass, char *bypassvalue,
|
||||
char *journalRegex, int shouldDebug) {
|
||||
char *createNewNote(char dirToVault[PATH_MAX], char *vaultFromDir, int bypass, char *bypassvalue, char *journalRegex, int shouldDebug) {
|
||||
// input from user for the name
|
||||
char *fileName = malloc(BUFFER_SIZE);
|
||||
if (!bypass) { // if we don't bypass. (if -n or --note weren't set.)
|
||||
@@ -96,10 +91,9 @@ char *createNewNote(char dirToVault[PATH_MAX], char *vaultFromDir, int bypass, c
|
||||
strncpy(fileName, bypassvalue, BUFFER_SIZE);
|
||||
fileName[BUFFER_SIZE - 1] = '\0';
|
||||
}
|
||||
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)
|
||||
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);
|
||||
@@ -138,11 +132,8 @@ char *createNewNote(char dirToVault[PATH_MAX], char *vaultFromDir, int bypass, c
|
||||
char *fileFullPath = malloc(PATH_MAX);
|
||||
snprintf(fileFullPath, PATH_MAX, "%s/%s/%s", dirToVault, vaultFromDir, fileName);
|
||||
int len = strlen(fileFullPath);
|
||||
if (fileFullPath[len - 3] != '.' || fileFullPath[len - 2] != 'm' ||
|
||||
fileFullPath[len - 1] != 'd') { // there might be a cleaner way to do this
|
||||
error(len > PATH_MAX - 3, "user",
|
||||
"%s is too big (greater than PATH_MAX-3) and we can't append .md",
|
||||
fileFullPath);
|
||||
if (fileFullPath[len - 3] != '.' || fileFullPath[len - 2] != 'm' || fileFullPath[len - 1] != 'd') { // there might be a cleaner way to do this
|
||||
error(len > PATH_MAX - 3, "user", "%s is too big (greater than PATH_MAX-3) and we can't append .md", fileFullPath);
|
||||
strncat(fileFullPath, ".md", PATH_MAX);
|
||||
// we checked before if fileName didn't already exist.
|
||||
// we must redo it as we add a .mode
|
||||
@@ -161,10 +152,9 @@ char *createNewNote(char dirToVault[PATH_MAX], char *vaultFromDir, int bypass, c
|
||||
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
|
||||
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
|
||||
@@ -194,8 +184,7 @@ char *fzfSelect(char *pathToFiles, char *selectText, int shouldDebug) {
|
||||
* Build index once into temp file
|
||||
* format: file:line:content
|
||||
*/
|
||||
snprintf(command, sizeof(command), "rg --line-number --no-heading --color=never . \"%s\" > %s",
|
||||
pathToFiles, indexFile);
|
||||
snprintf(command, sizeof(command), "rg --line-number --no-heading --color=never . \"%s\" > %s", pathToFiles, indexFile);
|
||||
|
||||
debug("INDEX CMD: %s", command);
|
||||
|
||||
@@ -243,14 +232,13 @@ char *fzfSelect(char *pathToFiles, char *selectText, int shouldDebug) {
|
||||
--bind 'change:show-preview'
|
||||
→ preview only appears after first selection change (not at startup)
|
||||
*/
|
||||
snprintf(
|
||||
command, sizeof(command),
|
||||
"cat %s | fzf --delimiter ':' --prompt='%s' "
|
||||
"--preview 'file={1}; line={2}; nl -ba \"$file\" | sed -n \"$((line-5)),$((line+5))p\" | "
|
||||
"sed \"$((line-$(($((line-5))))+1))s/^/\\x1b[31m-> \\x1b[0m/\"' "
|
||||
"--preview-window=right:60%%:hidden "
|
||||
"--bind 'change:show-preview'",
|
||||
indexFile, selectText ? selectText : "> ");
|
||||
snprintf(command, sizeof(command),
|
||||
"cat %s | fzf --delimiter ':' --prompt='%s' "
|
||||
"--preview 'file={1}; line={2}; nl -ba \"$file\" | sed -n \"$((line-5)),$((line+5))p\" | "
|
||||
"sed \"$((line-$(($((line-5))))+1))s/^/\\x1b[31m-> \\x1b[0m/\"' "
|
||||
"--preview-window=right:60%%:hidden "
|
||||
"--bind 'change:show-preview'",
|
||||
indexFile, selectText ? selectText : "> ");
|
||||
debug("FZF CMD: %s", command);
|
||||
|
||||
FILE *fzfPipe = popen(command, "r");
|
||||
@@ -284,11 +272,9 @@ char *fzfSelect(char *pathToFiles, char *selectText, int shouldDebug) {
|
||||
return result;
|
||||
}
|
||||
|
||||
char *ncursesSelect(
|
||||
char **options, char *optionsText, int optionsNumber, int extraOptionsNumber, char *bottomText,
|
||||
char *middleText, char *topText,
|
||||
int shouldDebug) { // TODO we should see how it handles larges strings (like large directories)
|
||||
int highlight = 0; // curently highlighted option
|
||||
char *ncursesSelect(char **options, char *optionsText, int optionsNumber, int extraOptionsNumber, char *bottomText, char *middleText, char *topText,
|
||||
int shouldDebug) { // TODO we should see how it handles larges strings (like large directories)
|
||||
int highlight = 0; // curently highlighted option
|
||||
int key;
|
||||
|
||||
cbreak(); // disable line buffering
|
||||
|
||||
@@ -21,16 +21,14 @@ also can create a journal if the name matches with journalRegex.
|
||||
returns the path to the note.
|
||||
If you want to bypass the input TUI set bypass to 1 and bypassvalue to the note name
|
||||
*/
|
||||
char *createNewNote(char dirToVault[PATH_MAX], char *vaultFromDir, int bypass, char *bypassvalue,
|
||||
char *journalRegex, int debug);
|
||||
char *createNewNote(char dirToVault[PATH_MAX], char *vaultFromDir, int bypass, char *bypassvalue, char *journalRegex, int debug);
|
||||
/*
|
||||
Chooses in which directory it want to create the vault.
|
||||
Uses ncurses to get an input from the user.
|
||||
Creates a new vault with this input.
|
||||
If vault already exists, prints a warning.
|
||||
returns nothing. */
|
||||
void createNewVault(char **directoriesArray, int directoryCount, char **vaultsArray, int vaultCount,
|
||||
int bypass, char *bypassvalue, int debug);
|
||||
void createNewVault(char **directoriesArray, int directoryCount, char **vaultsArray, int vaultCount, int bypass, char *bypassvalue, int debug);
|
||||
// uses fzf and ripgrep to search inside the files to choose between all the options.
|
||||
char *fzfSelect(char *pathToFiles, char *selectText, int shouldDebug);
|
||||
/*this function is used multiple times let the user select one options from many with ncurses in a
|
||||
@@ -42,6 +40,5 @@ extraOptions are options that are special and have a special color (for ex: "Del
|
||||
options text and the start of options. middleText (usally \n) is printed between options and
|
||||
extraOptions. bottomText is printed bellow. topText and middle must be exactly one line. If you want
|
||||
empty lines use " " and not "". returns the selected option. */
|
||||
char *ncursesSelect(char **options, char *optionsText, int optionsNumber, int extraOptionsNumber,
|
||||
char *bottomText, char *middleText, char *topText, int debug);
|
||||
char *ncursesSelect(char **options, char *optionsText, int optionsNumber, int extraOptionsNumber, char *bottomText, char *middleText, char *topText, int debug);
|
||||
#endif
|
||||
|
||||
+17
-33
@@ -23,8 +23,7 @@ void getCurrentTime(int *hour, int *minute, int *second) {
|
||||
*second = local->tm_sec; // Extract seconds
|
||||
}
|
||||
|
||||
void _debug(const int d, const char *file, const int line, const char *function,
|
||||
const char *message, ...) { // use for formatted debug
|
||||
void _debug(const int d, const char *file, const int line, const char *function, const char *message, ...) { // use for formatted debug
|
||||
if (d) {
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
@@ -32,8 +31,7 @@ void _debug(const int d, const char *file, const int line, const char *function,
|
||||
va_start(args, message);
|
||||
int h, m, s;
|
||||
getCurrentTime(&h, &m, &s);
|
||||
fprintf(stderr, "\e[0;32m[DEBUG -- %d:%d:%d] From file %s line %d function %s:\e[0m\n", h,
|
||||
m, s, file, line, function);
|
||||
fprintf(stderr, "\e[0;32m[DEBUG -- %d:%d:%d] From file %s line %d function %s:\e[0m\n", h, m, s, file, line, function);
|
||||
vfprintf(stderr, message, args);
|
||||
fprintf(stderr, "\e[0m\n");
|
||||
va_end(args);
|
||||
@@ -51,14 +49,12 @@ void _altDebug(const int d, const char *message,
|
||||
}
|
||||
}
|
||||
|
||||
void _error(const int shouldDebug, const int condition, const char *type, const char *file,
|
||||
const int line, const char *function, const char *message,
|
||||
void _error(const int shouldDebug, const int condition, const char *type, const char *file, const int line, const char *function, const char *message,
|
||||
...) { // used for formatted errors
|
||||
if (condition) {
|
||||
int h, m, s;
|
||||
getCurrentTime(&h, &m, &s);
|
||||
fprintf(stderr, "\e[0;31m[%s ERROR -- %d:%d:%d] From file %s line %d function %s:\n", type,
|
||||
h, m, s, file, line, function);
|
||||
fprintf(stderr, "\e[0;31m[%s ERROR -- %d:%d:%d] From file %s line %d function %s:\n", type, h, m, s, file, line, function);
|
||||
if (errno != 0) {
|
||||
fprintf(stderr, " (System-level error message: %s)\n", strerror(errno));
|
||||
} else {
|
||||
@@ -76,8 +72,7 @@ void _error(const int shouldDebug, const int condition, const char *type, const
|
||||
}
|
||||
}
|
||||
|
||||
static void copyDir(const char *source, const char *destination, const char **rsyncArgs,
|
||||
const int rsyncArgsNumber, const int shouldDebug) {
|
||||
static void copyDir(const char *source, const char *destination, const char **rsyncArgs, const int rsyncArgsNumber, const int shouldDebug) {
|
||||
debug("Backuping... source: %s and destination: %s", source, destination);
|
||||
debug("Rsync has %d extra arguments", rsyncArgsNumber);
|
||||
pid_t pid = fork();
|
||||
@@ -171,9 +166,7 @@ void initAppFilesAndDirs(const char *home, const int shouldDebug) {
|
||||
fclose(w);
|
||||
}
|
||||
|
||||
void handleBackups(char **sourceDirectoryArray, const int sourceNumber,
|
||||
char **destinationDirectoryArray, const char *homeDir, const int interval,
|
||||
const char **rsyncArguments, const int rsyncArgumentsNumber,
|
||||
void handleBackups(char **sourceDirectoryArray, const int sourceNumber, char **destinationDirectoryArray, const char *homeDir, const int interval, const char **rsyncArguments, const int rsyncArgumentsNumber,
|
||||
const int shouldDebug) {
|
||||
int shouldBackup = 0;
|
||||
time_t now = time(NULL);
|
||||
@@ -211,8 +204,7 @@ void handleBackups(char **sourceDirectoryArray, const int sourceNumber,
|
||||
}
|
||||
|
||||
if (difftime(now, lastBackupTime) > interval) {
|
||||
debug("(difftime) %d is greater than (interval) %d -> backuping...",
|
||||
difftime(now, lastBackupTime), interval);
|
||||
debug("(difftime) %d is greater than (interval) %d -> backuping...", difftime(now, lastBackupTime), interval);
|
||||
shouldBackup = 1;
|
||||
cacheFile = fopen(cacheFilePATH, "w");
|
||||
if (!cacheFile) {
|
||||
@@ -221,8 +213,7 @@ void handleBackups(char **sourceDirectoryArray, const int sourceNumber,
|
||||
fprintf(cacheFile, "%ld\n", (long)now);
|
||||
fclose(cacheFile);
|
||||
} else {
|
||||
debug("(difftime) %d is smaller than (interval) %d -> no need to backup.",
|
||||
difftime(now, lastBackupTime), interval);
|
||||
debug("(difftime) %d is smaller than (interval) %d -> no need to backup.", difftime(now, lastBackupTime), interval);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,8 +222,7 @@ void handleBackups(char **sourceDirectoryArray, const int sourceNumber,
|
||||
for (int i = 0; i < sourceNumber; i++) {
|
||||
debug("%s", destinationDirectoryArray[i]);
|
||||
if (destinationDirectoryArray[i]) { // if we don't want to backup it, it was set to NULL
|
||||
copyDir(sourceDirectoryArray[i], destinationDirectoryArray[i], rsyncArguments,
|
||||
rsyncArgumentsNumber, shouldDebug);
|
||||
copyDir(sourceDirectoryArray[i], destinationDirectoryArray[i], rsyncArguments, rsyncArgumentsNumber, shouldDebug);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -257,10 +247,9 @@ int isEditorValid(char *editorToCheck, int useDefaultEditor,
|
||||
}
|
||||
// check if installed
|
||||
char *editor;
|
||||
if (strcmp(editorToCheck, "neovim") ==
|
||||
0) { // some executables are not name the same as the project
|
||||
editor = strdup("nvim"); // we must use strdup and not just copy as we would have modified
|
||||
// editorToOpen in main
|
||||
if (strcmp(editorToCheck, "neovim") == 0) { // some executables are not name the same as the project
|
||||
editor = strdup("nvim"); // we must use strdup and not just copy as we would have modified
|
||||
// editorToOpen in main
|
||||
} else if (strcmp(editorToCheck, "helix") == 0) {
|
||||
editor = strdup("hx");
|
||||
} else if (strcmp(editorToCheck, "kakoune") == 0) {
|
||||
@@ -312,8 +301,7 @@ int isStringInArray(const char *string, const char **array, const int len) {
|
||||
|
||||
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);
|
||||
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) {
|
||||
@@ -361,8 +349,7 @@ void appendToFile(const char *path, const char *string, const int shouldDebug) {
|
||||
void sanitize(char *string) {
|
||||
size_t stringLenght = strlen(string);
|
||||
for (size_t i = 0; i < stringLenght; i++) {
|
||||
if ((!isalnum((unsigned char)string[i]) &&
|
||||
strchr("~/\\:*?\"\'|!$[]{}<>\n\r\t", string[i]))) { // replace unwanted chars by '_'
|
||||
if ((!isalnum((unsigned char)string[i]) && strchr("~/\\:*?\"\'|!$[]{}<>\n\r\t", string[i]))) { // replace unwanted chars by '_'
|
||||
string[i] = '_';
|
||||
}
|
||||
}
|
||||
@@ -387,9 +374,7 @@ int unlink_cb(const char *filePath, const struct stat *sb, int typeflag, struct
|
||||
|
||||
// some sanity checks to be sure that we don't delete something we shouldn't
|
||||
error(strcmp(filePath, "") == 0, "program", "filePath is empty. Refusing to delete directory");
|
||||
error(filePath[0] == '.', "program",
|
||||
"%s starts with \".\". For security reasons, use absolute path and not relative path.",
|
||||
filePath);
|
||||
error(filePath[0] == '.', "program", "%s starts with \".\". For security reasons, use absolute path and not relative path.", filePath);
|
||||
|
||||
int rv = remove(filePath);
|
||||
error(rv, "program", "remove() failed to delete %s", filePath);
|
||||
@@ -661,9 +646,8 @@ int openEditor(char *path, char *editor, int render, int shouldJumpToEndOfFile,
|
||||
// PARENT: wait ONLY editor
|
||||
// =========================
|
||||
int status;
|
||||
while (waitpid(editor_pid, &status, 0) ==
|
||||
-1) { // we can't just use waitpid(). Because when resizing the terminal, waitpid() is
|
||||
// returned so we loop to see if there is not a problem
|
||||
while (waitpid(editor_pid, &status, 0) == -1) { // we can't just use waitpid(). Because when resizing the terminal, waitpid() is
|
||||
// returned so we loop to see if there is not a problem
|
||||
if (errno != EINTR) {
|
||||
perror("waitpid");
|
||||
break;
|
||||
|
||||
+6
-11
@@ -26,11 +26,9 @@
|
||||
#define DAILY 86400
|
||||
#define WEEKLY 604800
|
||||
#define MONTHLY 2628000 // calculated from the average lenght of a non leap year
|
||||
#define debug(message, ...) \
|
||||
_debug(shouldDebug, __FILE__, __LINE__, __func__, message, ##__VA_ARGS__)
|
||||
#define debug(message, ...) _debug(shouldDebug, __FILE__, __LINE__, __func__, message, ##__VA_ARGS__)
|
||||
#define altDebug(message, ...) _altDebug(shouldDebug, message, ##__VA_ARGS__)
|
||||
#define error(condition, type, message, ...) \
|
||||
_error(shouldDebug, condition, type, __FILE__, __LINE__, __func__, message, ##__VA_ARGS__)
|
||||
#define error(condition, type, message, ...) _error(shouldDebug, condition, type, __FILE__, __LINE__, __func__, message, ##__VA_ARGS__)
|
||||
// you must edit this two values if you want to add suport for an editor
|
||||
extern const char *supportedEditor[]; // array of supported editors
|
||||
extern const int numEditors; // number of supported editors
|
||||
@@ -48,13 +46,11 @@ int reverseCompareString(const void *a, const void *b);
|
||||
int isEditorValid(char *editorToCheck, int useDefaultEditor, int debug);
|
||||
// please use the macro debug instead of _debug.
|
||||
// formated debugging.
|
||||
void _debug(const int d, const char *file, const int line, const char *function,
|
||||
const char *message, ...);
|
||||
void _debug(const int d, const char *file, const int line, const char *function, const char *message, ...);
|
||||
// use for less formal debuggin. (usefull if enumerating or making a list).
|
||||
void _altDebug(const int d, const char *message, ...);
|
||||
// formated error.
|
||||
void _error(const int shouldDebug, const int condition, const char *type, const char *file,
|
||||
const int line, const char *function, const char *message, ...);
|
||||
void _error(const int shouldDebug, const int condition, const char *type, const char *file, const int line, const char *function, const char *message, ...);
|
||||
// Returns 1 if the string is 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.
|
||||
@@ -86,7 +82,6 @@ Each pair of source/destination will launch one rsync process.
|
||||
If a pair don't need to be backed up, the destination should be set to NULL.
|
||||
rsyncArgs is the array of arguments to be passed to rsync. Do not inclue destination or source. It
|
||||
will be added in the function.*/
|
||||
void handleBackups(char **sourceDirectoryArray, const int sourceDirectoryNumber,
|
||||
char **destinationDirectoryArray, const char *homeDir, const int interval,
|
||||
const char **rsyncArgs, const int rsyncArgsNumber, const int shouldDebug);
|
||||
void handleBackups(char **sourceDirectoryArray, const int sourceDirectoryNumber, char **destinationDirectoryArray, const char *homeDir, const int interval, const char **rsyncArgs, const int rsyncArgsNumber,
|
||||
const int shouldDebug);
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user