Added first part of journal code and debug(), altDebug() and error()

This commit is contained in:
Tomas Rivera
2026-04-03 10:42:54 +02:00
parent d24ae49a59
commit 6135ff9e00
5 changed files with 258 additions and 221 deletions
+2 -1
View File
@@ -2,5 +2,6 @@
"directory": "$/Documents/Notes/", "directory": "$/Documents/Notes/",
"render": true, "render": true,
"jumpToEndOfFileOnLaunch": true, "jumpToEndOfFileOnLaunch": true,
"editor": "neovim" "editor": "neovim",
"journalRegex": ".*journal.*"
} }
+69 -115
View File
@@ -14,11 +14,11 @@
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
int debug = 0; int shouldDebug = 0;
// all of the argument parsing is done after so flags overwrite config options. The only config options that can't be set in the config is the debug // all of the argument parsing is done after so flags overwrite config options. The only config options that can't be set in the config is the shouldDebug
for (int i = 1; i < argc; i++) { for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "-V") == 0 || strcmp(argv[i], "--verbose") == 0) { if (strcmp(argv[i], "-V") == 0 || strcmp(argv[i], "--verbose") == 0) {
debug = 1; shouldDebug = 1;
} }
} }
@@ -29,23 +29,17 @@ int main(int argc, char *argv[]) {
// gets the home directory // gets the home directory
struct passwd *pw = getpwuid(getuid()); struct passwd *pw = getpwuid(getuid());
const char *homedir = pw->pw_dir; const char *homedir = pw->pw_dir;
//(TODO LATER) maybe add a flag to specify path to config
// check if the config file exists // check if the config file exists
char configPath[PATH_MAX]; char configPath[PATH_MAX];
snprintf(configPath, sizeof(configPath), "%s/.config/notewrapper/config.json", homedir); snprintf(configPath, sizeof(configPath), "%s/.config/notewrapper/config.json", homedir);
if (debug) {printf("\e[0;32m[DEBUG]\e[0m the path to the config file is %s\n", configPath);} debug("Path to the config file is %s", configPath);
if (stat(configPath, &(struct stat){0}) == -1) { // if the config directory do not exist error(stat(configPath, &(struct stat){0}) == -1, "program", "The config file %s does not exist.\nMaybe try the default path to the config ~/.config/notewrapper/config.json\nIf it still does not work, compiling the program with make should create a valid config file.", configPath); // if the config directory does not exist
printf("\e[0;31mERROR: the config file (\e[0;32m$/.config/notewrapper/config.json\e[0;31m) does not exist.\nCompiling the program with \e[0;32mmake\e[0;31m should solve this error.\e[0m\n");
exit(1); // (TODO LATER) This might lack of shouldDebug info
}
// (TODO LATER) This might lack of debug info
// opens config.json // opens config.json
FILE *f = fopen(configPath, "r"); FILE *f = fopen(configPath, "r");
if (!f) { error(!f, "program", "The config file does exist, but can not be open.");
printf("\e[0;31mERROR: The config file does exist, but can not be open. Something went wrong.\e[0;32m\n");
exit(1);
}
// loads and read the config file // loads and read the config file
//gets the size //gets the size
@@ -54,29 +48,20 @@ int main(int argc, char *argv[]) {
rewind(f); rewind(f);
//gets the data //gets the data
char *data = malloc(size+1); char *data = malloc(size+1);
if (!data) { error(!data, "program", "malloc failed allocating memory for the variable data.");
fclose(f);
printf("\e[0;31mERROR: malloc failed allocating memory for the variable data. Something went wrong.\e[0m\n");
exit(1);
}
size_t readBytes = fread(data, 1, size, f); // 1 --> size of each item size_t readBytes = fread(data, 1, size, f); // 1 --> size of each item
if (readBytes != size) {
printf("\e[0;31mERROR: Failed to read config file (%zu bytes read, expected %ld)\e[0m\n", readBytes, size); if (readBytes!=size) {free(data);fclose(f);}
free(data); error(readBytes!=size, "program", "Failed to read config file (&zu bytes read, expected %ld)", readBytes, size);
fclose(f);
exit(1);
}
data[size] = '\0'; data[size] = '\0';
fclose(f); fclose(f);
// parse the JSON // parse the JSON
cJSON *json = cJSON_Parse(data); cJSON *json = cJSON_Parse(data);
if (!json) { if (!json) {free(data);}
printf("\e[0;31mERROR: JSON parse error\e[0m\n"); // (TODO LATER) replace all printf("\e[0;31m with fpintf(stderr( "\e[0;31m and maybe debug messages too error(!json, "program", "JSON parse error");
free(data);
exit(1);
}
// (TODO LATER) maybe add a default vault option // (TODO LATER) maybe add a default vault option
cJSON *dirJson = cJSON_GetObjectItem(json, "directory"); cJSON *dirJson = cJSON_GetObjectItem(json, "directory");
char *notesDirectoryString = malloc(PATH_MAX); char *notesDirectoryString = malloc(PATH_MAX);
@@ -106,19 +91,16 @@ int main(int argc, char *argv[]) {
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)) {
if (debug) {printf("\e[0;32m[DEBUG]\e[0m Editor in config.json is %s\n", editorToOpenJSON->valuestring);} debug("Editor in config.json is %s", editorToOpenJSON->valuestring);
if (!isStringInArray(editorToOpenJSON->valuestring, supportedEditor, numEditors)) { // if we don't support this editor error(!isStringInArray(editorToOpenJSON->valuestring, supportedEditor, numEditors), "user", "%s (fetched from config.json) is not a supported editor.");
printf("\e[0;31mERROR: %s (fetched from config.json) is not a supported editor. Supported editors are ", editorToOpenJSON->valuestring);
for (int i = 0; i < numEditors; i++) {
if (i < numEditors-2) {printf("\e[0;32m%s\e[0;31m, ", supportedEditor[i]);} // this if () {} else {} is used to get something like this "editor1, editor2, [...], editorn-2, editorn-1 and editorn"
else if (i == numEditors-2) {printf("\e[0;32m%s\e[0;31m and ", supportedEditor[i]);}
else {printf("\e[0;32m%s\e[0;31m.", supportedEditor[i]);}
}
printf("\e[0m\n");
exit(1);
}
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)
} }
cJSON *journalRegexJSON = cJSON_GetObjectItem(json, "journalRegex");
char *journalRegex = ".*journal.*"; // default regex pattern for the journal
if (journalRegexJSON || cJSON_IsString(journalRegexJSON)) {
debug("The regex in config.json is %s", journalRegexJSON->valuestring);
journalRegex = strdup(journalRegexJSON->valuestring);
}
//cleans up //cleans up
cJSON_Delete(json); cJSON_Delete(json);
free(data); free(data);
@@ -151,31 +133,18 @@ int main(int argc, char *argv[]) {
printf("There is still no released version\n"); printf("There is still no released version\n");
return 0; return 0;
} else if (strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "--directory") == 0) { } else if (strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "--directory") == 0) {
if (i+1 == argc) { // if -nd or --directory was the last argument error(i+1==argc, "user", "Missing argument. Please use -d <path/to/directory> or --directory <path/to/directory>.");
printf("\e[0;31mERROR: Missing argument. Please use -d <path/to/directory> or --directory <path/to/directory>.\e[0m\n");
exit(1);
}
notesDirectoryString = argv[i+1]; notesDirectoryString = argv[i+1];
// (TODO LATER) Add a check if there is a arg after, if it is a directory, expand $, work with . and .., check if there is a dir. // (TODO LATER) Add a check if there is a arg after, if it is a directory, expand $, work with . and .., check if there is a dir.
// it works with .. and . if the dir exists // it works with .. and . if the dir exists
// (TODO LATER) Add debug info for this flag and others // (TODO LATER) Add shouldDebug info for this flag and others
} else if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--vault") == 0) { } else if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--vault") == 0) {
if (i+1 == argc) { // if -v or --vault was the last argument error(i+1==argc, "user", "Missing argument. Pleaase use -v <vault's name> or --vault <vault's name>");
printf("\e[0;31mERROR: Missing argument. Please use -v <vault's name> or --vault <vault's name>.\e[0m\n");
exit(1);
}
bypassVaultSelection = argv[i+1]; // (TODO LATER) Add security checks pass ti strndup. and if vault don't exist create one. SEE (TODO LATER) where bypassVaultSelection is checked bypassVaultSelection = argv[i+1]; // (TODO LATER) Add security checks pass ti strndup. and if vault don't exist create one. SEE (TODO LATER) where bypassVaultSelection is checked
} else if (strcmp(argv[i], "-n") == 0 || strcmp(argv[i], "--note") == 0) { // (TODO LATER) Broken if we put the -v flag after the -n flag } else if (strcmp(argv[i], "-n") == 0 || strcmp(argv[i], "--note") == 0) { // (TODO LATER) Broken if we put the -v flag after the -n flag
if (i+1 == argc) { // if -n or --note was the last argument error(i+1==argc, "user", "Missing argument. Please user -n <note's name> or --note <note's name>.");
printf("\e[0;31mERROR: Missing argument. Please use -n <note's name> or --note <note's name>.\e[0m\n"); error(strcmp(bypassVaultSelection, HASH_MACRO) == 0, "user", "If you want to specify the note, you must also specify the vault with -v <vault's name> or --vault <vault's name>.");
exit(1); bypassNoteSelection = argv[i+1];
} else if (strcmp(bypassVaultSelection, HASH_MACRO) == 0) { // bypassVaultSelection is initialized to HASH_MACRO, if it is not changed it means -v wasn't specified
printf("\e[0;31mERROR: If you want to specify the note, you must also specify the vault with -v <vault's name> or --vault <vault's name>\e[0m\n");
exit(1);
} else {
bypassNoteSelection = argv[i+1];
}
} else if (strcmp(argv[i], "-j") == 0 || strcmp(argv[i], "--jump") == 0) { } else if (strcmp(argv[i], "-j") == 0 || strcmp(argv[i], "--jump") == 0) {
shouldJumpToEnd = 1; shouldJumpToEnd = 1;
} else if (strcmp(argv[i], "-J") == 0 || strcmp(argv[i], "--no-jump") == 0) { } else if (strcmp(argv[i], "-J") == 0 || strcmp(argv[i], "--no-jump") == 0) {
@@ -185,47 +154,25 @@ int main(int argc, char *argv[]) {
} else if (strcmp(argv[i], "-R") == 0 || strcmp(argv[i], "--no-render") == 0) { } else if (strcmp(argv[i], "-R") == 0 || strcmp(argv[i], "--no-render") == 0) {
shouldRender = 0; shouldRender = 0;
} else if (strcmp(argv[i], "-e") == 0 || strcmp(argv[i], "--editor") == 0) { } else if (strcmp(argv[i], "-e") == 0 || strcmp(argv[i], "--editor") == 0) {
if (i+1 == argc) { // if -e or --editor was the last argument error(i+1==argc, "user", "Missing argument. Please use -e <editor> or --editor <editor>.");
printf("\e[0;31mERROR: Missing argument. Please use -e <editor> or --editor <editor>.\e[0m\n"); editorToOpen = argv[i+1];
exit(1); debug("Editor specified with -e or --editor is %s", editorToOpen);
}
editorToOpen = argv[i+1];
if (debug) {
printf("\e[0;32m[DEBUG]\e[0m Editor specified with -e or --editor is %s\n", editorToOpen);
}
if (!isStringInArray(editorToOpen, supportedEditor, numEditors)) { // if we don't support this editor
printf("\e[0;31mERROR: %s (specified with -e or --editor) is not a supported editor. Supported editors are ", editorToOpen);
for (int i = 0; i < numEditors; i++) {
if (i < numEditors-2) {
printf("\e[0;32m%s\e[0;31m, ", supportedEditor[i]); // this if () {} else {} is used to get something like this "editor1, editor2, [...], editorn-2, editorn-1 and editorn"
} else if (i == numEditors-2) {
printf("\e[0;32m%s\e[0;31m and ", supportedEditor[i]);
} else {printf("\e[0;32m%s\e[0;31m.", supportedEditor[i]);
}
}
printf("\e[0m\n");
exit(1);
}
} }
} }
error(!doesEditorExist(editorToOpen, shouldDebug), "user", "%s is either not in your path or not installed.", editorToOpen);
if (!doesEditorExist(editorToOpen, debug)) { // check if the editor is in your PATH
printf("\e[0;31mERROR: %s is either not in your path or not installed.\e[0m\n", editorToOpen);
exit(1);
}
int shouldExit = 0; int shouldExit = 0;
while(!shouldExit) { while(!shouldExit) {
// this loop is the vault selector // this loop is the vault selector
size_t vaultsCount = 0; size_t vaultsCount = 0;
char **vaultsArray = getVaultsFromDirectory(notesDirectoryString, &vaultsCount, debug); char **vaultsArray = getVaultsFromDirectory(notesDirectoryString, &vaultsCount, shouldDebug);
qsort(vaultsArray, vaultsCount, sizeof(const char *), compareString); // sorts the vaults alphabetically qsort(vaultsArray, vaultsCount, sizeof(const char *), compareString); // sorts the vaults alphabetically
if (debug) { debug("Available vaults");
printf("┌------------------------------\n\e[0;32m[DEBUG]\e[0m Available vaults:\n"); if (shouldDebug) {
for (size_t i = 0; i < vaultsCount; i++) { for (size_t i = 0; i < vaultsCount; i++) {
printf("%s\n", vaultsArray[i]); altDebug("%s\n", vaultsArray[i]);
} }
printf("└ ------------------------------\n"); altDebug("└ ------------------------------\n");
} }
// adds "create a new vault" into the vaultsArray // adds "create a new vault" into the vaultsArray
@@ -243,7 +190,7 @@ int main(int argc, char *argv[]) {
vaultSelected = bypassVaultSelection; vaultSelected = bypassVaultSelection;
goto note_selection; goto note_selection;
} }
vaultSelected = ncursesSelect(vaultsArray, "Select vault (Use arrows or WASD, Enter to select):", vaultsCount, extraOptions, debug); vaultSelected = ncursesSelect(vaultsArray, "Select vault (Use arrows or WASD, Enter to select):", vaultsCount, extraOptions, 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) // 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++) { for (int i = 0; i < vaultsCount; i++) {
@@ -253,8 +200,7 @@ int main(int argc, char *argv[]) {
} }
free(vaultsArray); free(vaultsArray);
if (debug) {printf("\e[0;32m[DEBUG]\e[0m Selected vault:%s\n", vaultSelected);} 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: note_selection:
bypassVaultSelection = HASH_MACRO; // we must reset bypassVaultSelection to not get stuck in a infinite loop of bypassing bypassVaultSelection = HASH_MACRO; // we must reset bypassVaultSelection to not get stuck in a infinite loop of bypassing
@@ -262,15 +208,24 @@ note_selection:
while (!shouldExit && !shouldChangeVault) { while (!shouldExit && !shouldChangeVault) {
// this loop is the note selector // this loop is the note selector
int filesCount = 0; int filesCount = 0;
char **filesArray = getNotesFromVault(notesDirectoryString, vaultSelected, &filesCount, debug); char **filesArray = getNotesFromVault(notesDirectoryString, vaultSelected, journalRegex, &filesCount, shouldDebug);
qsort(filesArray, filesCount, sizeof(const char *), compareString); // sorts the notes alphabetically qsort(filesArray, filesCount, sizeof(const char *), compareString); // sorts the notes alphabetically
int journalCount = 0;
if (debug) { char **journalArray = getJournalsFromVault(notesDirectoryString, vaultSelected, journalRegex, &journalCount, shouldDebug);
printf("┌------------------------------\n\e[0;32m[DEBUG]\e[0m Available notes:\n"); qsort(journalArray, journalCount, sizeof(const char *), compareString);
// appends the journal at the end of filesArray
filesArray = realloc(filesArray, (filesCount + journalCount)*sizeof(char*));
for (int i = 0; i < journalCount; i++) {
filesArray[i + filesCount] = journalArray[i];
}
filesCount = filesCount + journalCount;
debug("Available notes and journals:");
if (shouldDebug) {
for (size_t i = 0; i < filesCount; i++) { for (size_t i = 0; i < filesCount; i++) {
printf("%s\n", filesArray[i]); altDebug("%s\n", filesArray[i]);
} }
printf(" ------------------------------\n"); altDebug("└------------------------------\n");
} }
// adds options // adds options
int extraNotesOptions = 4; int extraNotesOptions = 4;
@@ -281,7 +236,7 @@ note_selection:
filesArray[filesCount+3] = "Quit (Ctrl+C)"; filesArray[filesCount+3] = "Quit (Ctrl+C)";
char *noteSelected; char *noteSelected;
if (strcmp(bypassNoteSelection, HASH_MACRO) != 0) { if (strcmp(bypassNoteSelection, HASH_MACRO) != 0) {
// (TODO LATER) Add debug info // (TODO LATER) Add shouldDebug info
noteSelected = bypassNoteSelection; noteSelected = bypassNoteSelection;
if (isStringInArray(noteSelected, (const char **)filesArray, filesCount + extraNotesOptions)) {// (TODO LATER) Handle the case where the note name is one of the extraOptions if (isStringInArray(noteSelected, (const char **)filesArray, filesCount + extraNotesOptions)) {// (TODO LATER) Handle the case where the note name is one of the extraOptions
goto open_note; goto open_note;
@@ -289,7 +244,7 @@ note_selection:
goto note_creation; goto note_creation;
} }
} }
noteSelected = ncursesSelect(filesArray, "Select note (Use arrows or WASD, Enter to select):", filesCount, extraNotesOptions, debug); noteSelected = ncursesSelect(filesArray, "Select note (Use arrows or WASD, Enter to select):", filesCount, extraNotesOptions, 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) // 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++) { 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 if (noteSelected != filesArray[i]) { // we must prevent noteSelected to be freed. It will cause a lot of problems
@@ -297,47 +252,46 @@ note_selection:
} }
} }
free(filesArray); free(filesArray);
if (debug) {printf("\e[0;32m[DEBUG]\e[0m Selected note: %s\n", noteSelected);} debug("Selected note: %s", noteSelected);
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[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
openEditor(fullPath, editorToOpen, shouldRender, shouldJumpToEnd, debug); openEditor(fullPath, editorToOpen, shouldRender, shouldJumpToEnd, shouldDebug);
} 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, debug); char *pathForNoteCreation = createNewNote(notesDirectoryString, vaultSelected, bypassNoteSelection, shouldDebug);
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
openEditor(pathForNoteCreation, editorToOpen, shouldRender, shouldJumpToEnd, debug); 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) {
shouldChangeVault = 1; shouldChangeVault = 1;
} else if (strcmp(noteSelected, "Delete vault") == 0) { } else if (strcmp(noteSelected, "Delete vault") == 0) {
const char *yesNo[] = {"No, go back to note selection.", "Yes."}; 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.", 1, 1, debug); char *answer = ncursesSelect((char **)yesNo, "Are you sure you want to delete the entire vault? This can not be undone.", 1, 1, shouldDebug);
if (debug) {printf("\e[0;32m[DEBUG]\e[0mYou answered: \e[0;32m%s\e[0m for deleting the vault named \e[0;32m%s\e[0m\n", answer, vaultSelected);} debug("You answered: %s for deleting the vault %s", answer, vaultSelected);
if (strcmp(answer, "Yes.") == 0) { if (strcmp(answer, "Yes.") == 0) {
// delete the vault after confirmation by the user // delete the vault after confirmation by the user
char pathToRMRF[PATH_MAX]; char pathToRMRF[PATH_MAX];
sprintf(pathToRMRF, "%s/%s", notesDirectoryString, vaultSelected); sprintf(pathToRMRF, "%s/%s", notesDirectoryString, vaultSelected);
if (debug) {printf("\e[0;32m[DEBUG]\e[0m Removed the directory: \e[0;32m%s\e[0m\n", pathToRMRF);} debug("Removed the directory: %s", pathToRMRF);
rmrf(pathToRMRF); rmrf(pathToRMRF);
shouldChangeVault = 1; shouldChangeVault = 1;
} }
} else if (strcmp(noteSelected,"Quit (Ctrl+C)") == 0) { } else if (strcmp(noteSelected,"Quit (Ctrl+C)") == 0) {
if (debug) {printf("\e[0;32m[DEBUG]\e[0m The program was exited,\n");} debug("The program was exited.");
shouldExit = 1; shouldExit = 1;
} }
} }
} else if (strcmp(vaultSelected,"Create a new vault") == 0) { } else if (strcmp(vaultSelected,"Create a new vault") == 0) {
createNewVault(notesDirectoryString, debug); createNewVault(notesDirectoryString, shouldDebug);
} else if (strcmp(vaultSelected,"Settings") == 0) { } else if (strcmp(vaultSelected,"Settings") == 0) {
// (TODO LATER) add a way to modify the path to config.json // (TODO LATER) add a way to modify the path to config.json
openEditor(configPath, editorToOpen, 0, 0, debug); // 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) { } else if (strcmp(vaultSelected,"Quit (Ctrl+C)") == 0) {
if (debug) {printf("\e[0;32m[DEBUG]\e[0m The program was exited.\n");} debug("The program was exited");
shouldExit = 1; shouldExit = 1;
} }
} }
+13 -23
View File
@@ -1,6 +1,7 @@
#include "ui.h" #include "ui.h"
void createNewVault(char *dirToVault, int debug) { void createNewVault(char *dirToVault, int shouldDebug) {
// (TODO LATER) warn if it matches the regex for the journal
//(TODO LATER) add a way to go back to vault selection //(TODO LATER) add a way to go back to vault selection
int duplicateWarning = 0; // set to 1 later if the vault you tried to create already existed int duplicateWarning = 0; // set to 1 later if the vault you tried to create already existed
input_screen: input_screen:
@@ -27,14 +28,11 @@ input_screen:
wgetnstr(stdscr, vaultName, sizeof(vaultName)-1); wgetnstr(stdscr, vaultName, sizeof(vaultName)-1);
refresh(); refresh();
endwin(); endwin();
if (strcmp(vaultName, "") == 0) { error(strcmp(vaultName, "") == 0, "user", "vaultName is empty"); // (TODO LATER) replace that with a warning
printf("\e[0;31mERROR: vaultName is empty\e[0m\n"); debug("Inputed vaultName=%s", vaultName);
exit(1);
}
if (debug) {printf("\e[0;32m[DEBUG]\e[0m inputed vaultName=%s\n", vaultName);}
sanitize(vaultName); sanitize(vaultName);
if (debug) {printf("\e[0;32m[DEBUG]\e[0m sanitized vaultName=%s\n", vaultName);} debug("Sanitized vaultName=%s", vaultName);
struct stat st = {0}; // https://stackoverflow.com/a/7430262 struct stat st = {0}; // https://stackoverflow.com/a/7430262
char vaultFullPath[PATH_MAX]; char vaultFullPath[PATH_MAX];
sprintf(vaultFullPath, "%s/%s/", dirToVault, vaultName); sprintf(vaultFullPath, "%s/%s/", dirToVault, vaultName);
@@ -48,7 +46,7 @@ input_screen:
} }
char *createNewNote(char dirToVault[PATH_MAX], char *vaultFromDir, char *bypass, int debug) { char *createNewNote(char dirToVault[PATH_MAX], char *vaultFromDir, char *bypass, int shouldDebug) {
// (TODO LATER) Add check. If the user creates a note with a name that already exists. it erases the old one // (TODO LATER) Add check. If the user creates a note with a name that already exists. it erases the old one
// input from user for the name // input from user for the name
char fileName[256]; char fileName[256];
@@ -68,35 +66,27 @@ char *createNewNote(char dirToVault[PATH_MAX], char *vaultFromDir, char *bypass,
fileName[sizeof(fileName)-1] = '\0'; fileName[sizeof(fileName)-1] = '\0';
} }
// (TODO LATER) add a way to go back to note selection // (TODO LATER) add a way to go back to note selection
if (strcmp(fileName, "") == 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)
printf("\e[0;32mERROR: fileName is empty\e[0m\n"); // (TODO LATER) it should just go back to the note creation with a warning
exit(1);
}
// check/sanitize the input // check/sanitize the input
if (debug) {printf("\e[0;32m[DEBUG]\e[0m inputed fileName=%s\n", fileName);} debug("Inputed fileName=%s", fileName);
sanitize(fileName); sanitize(fileName);
// if there is no .md add an .md // if there is no .md add an .md
int len = strlen(fileName); int len = strlen(fileName);
if (fileName[len-1] != 'd' || fileName[len-2] != 'm' || fileName[len-3] != '.') { // there might be a cleaner way to do this if (fileName[len-1] != 'd' || fileName[len-2] != 'm' || fileName[len-3] != '.') { // there might be a cleaner way to do this
strcat(fileName, ".md"); // this should not cause an overflow issue as we get at most 252 chars (+'.'+'m'+'d'+'\0' makes it to 256) with wgetnstr 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 (debug) {printf("\e[0;32m[DEBUG]\e[0m sanitize(fileName)=%s\n", fileName);} // (TODO LATER) Check if dirToVault+vaultFromDir+fileName > PATH_MAX debug("Sanitized fileName=%s", fileName);
char *fileFullPath = malloc(PATH_MAX); // this dinamically allocated because we use it in the main function to call openEditor char *fileFullPath = malloc(PATH_MAX); // this dinamically allocated because we use it in the main function to call openEditor
sprintf(fileFullPath, "%s/%s/%s", dirToVault, vaultFromDir, fileName); sprintf(fileFullPath, "%s/%s/%s", dirToVault, vaultFromDir, fileName);
FILE *filePointer; FILE *filePointer;
filePointer = fopen(fileFullPath, "w"); // creates and opens the file filePointer = fopen(fileFullPath, "w"); // creates and opens the file (TODO LATER) Maybe check if the file really doesn't exist
if (filePointer == NULL) { error(filePointer == NULL, "program", "The %s couldn't be created.", fileFullPath);
printf("\e[0;31mERROR: The file couldn't be created. Something went wrong.\e[0m\n");
free(fileFullPath);
exit(1);
}
fprintf(filePointer, "### %s\n", fileName); //(TODO LATER) Add a way to configure default behaviour when creating a file fprintf(filePointer, "### %s\n", fileName); //(TODO LATER) Add a way to configure default behaviour when creating a file
fclose(filePointer); // closes the file so that nvim could open it fclose(filePointer); // closes the file so that nvim could open it
return fileFullPath; return fileFullPath;
} }
char* ncursesSelect(char **options, char *optionsText, size_t optionsNumber, size_t extraOptionsNumber, int debug) { char* ncursesSelect(char **options, char *optionsText, size_t optionsNumber, size_t extraOptionsNumber, int shouldDebug) {
int highlight = 0; //curently highlighted option int highlight = 0; //curently highlighted option
int key; int key;
+153 -79
View File
@@ -3,13 +3,56 @@
const char *supportedEditor[] = {"neovim", "vim"}; const char *supportedEditor[] = {"neovim", "vim"};
const int numEditors = 2; const int numEditors = 2;
//(TODO LATER) We should write a debug() function and an error(function)
int compareString(const void *a, const void *b) { int compareString(const void *a, const void *b) {
const char *str1 = *(const char **)a; const char *str1 = *(const char **)a;
const char *str2 = *(const char **)b; const char *str2 = *(const char **)b;
return strcmp(str1, str2); // strcmp returns <0, 0, >0 return strcmp(str1, str2); // strcmp returns <0, 0, >0
} }
int doesEditorExist (char *editorToCheck, int debug) { // Some exectuables have not exaclty the same name as the editor. void _debug(const int d, const char *file, const int line, const char *function, const char *message, ...) { // use for formatted debug
if (d) {
va_list args; //variadic function stuff
va_start(args, message);
fprintf(stderr, "\e[0;32m[DEBUG] From file %s line %d function %s:\e[0m\n", file, line, function);
vfprintf(stderr, message, args);
printf("\e[0m\n");
va_end(args);
}
}
void _altDebug(const int d, const char *message, ...) { // use for less formal debuggin. (usefull if enumerating or making a list
if (d) {
va_list args;
va_start(args, message);
vfprintf(stderr, message, args);
va_end(args);
}
}
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) {
fprintf(stderr, "\e[0;31m[%s ERROR] From file %s line %d function %s:\n", type, file, line, function);
if (errno != 0) {
fprintf(stderr, " (System-level error message: %s)\n", strerror(errno));
} else {
fprintf(stderr, " (No system-level error; issue is application-level)\n");
}
va_list args;
va_start(args, message);
vfprintf(stderr, message, args);
va_end(args);
if (!shouldDebug) {
fprintf(stderr, "\nRunning notewrapper -V might give you more information.");
}
fprintf(stderr, "\e[0m\n");
exit(1);
}
}
int doesEditorExist (char *editorToCheck, int shouldDebug) { // Some exectuables have not exaclty the same name as the editor.
char *editor; char *editor;
if (strcmp(editorToCheck, "neovim") == 0) { if (strcmp(editorToCheck, "neovim") == 0) {
editor = strdup("nvim"); // we must use strdup and not just copy as we would have modified editorToOpen in main editor = strdup("nvim"); // we must use strdup and not just copy as we would have modified editorToOpen in main
@@ -18,11 +61,8 @@ int doesEditorExist (char *editorToCheck, int debug) { // Some exectuables h
editor = strdup(editorToCheck); editor = strdup(editorToCheck);
} }
char *path_env = getenv("PATH"); char *path_env = getenv("PATH");
if (!path_env) { error(!path_env, "program", "getenv(\"PATH\") failed to get your path. NoteWrapper is unable to check if your desired editor is installed\n");
printf("\e[0;31mERROR: getenv(\"PATH\") failed to get your path. NoteWrapper is unable to check if your desired editor is installed\n"); debug("Your PATH is %s", path_env);
exit(1);
};
if (debug) {printf("\e[0;32m[DEBUG]\e[0m Your PATH is %s\n", path_env);}
char *paths = strdup(path_env); // duplicate because strtok modifies the string char *paths = strdup(path_env); // duplicate because strtok modifies the string
char *dir = strtok(paths, ":"); char *dir = strtok(paths, ":");
while (dir) { while (dir) {
@@ -65,38 +105,34 @@ void sanitize(char *string) {
// so it walks the file tree and deletes it's content before removing the directory // so it walks the file tree and deletes it's content before removing the directory
// (TODO LATER) this seems safe, but it's maybe a good idea to add some checks to not remove something it should not remove // (TODO LATER) this seems safe, but it's maybe a good idea to add some checks to not remove something it should not remove
int unlink_cb(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) { int unlink_cb(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) {
int rv = remove(fpath); int shouldDebug = 1; //normally shouldDebug should be passed to the function. However, it's to difficult here and the best it to set it to 1.
int rv = remove(fpath);
if (rv) error(rv, "program", "remove() failed to delete %s", fpath);
perror(fpath); return rv;
return rv;
} }
int rmrf(char *path) { int rmrf(char *path) {
// (TODO LATER) Check if it not a root directory or something like this
return nftw(path, unlink_cb, 64, FTW_DEPTH | FTW_PHYS); return nftw(path, unlink_cb, 64, FTW_DEPTH | FTW_PHYS);
} }
char** getVaultsFromDirectory(char *dirString, size_t *count, int debug) { 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
if (debug) {printf("\e[0;32m[DEBUG]\e[0m Opening %s aka the directory of vaults\n", dirString);} debug("Opening %s", dirString);
// originally from https://www.geeksforgeeks.org/c/c-program-list-files-sub-directories-directory/ // originally from https://www.geeksforgeeks.org/c/c-program-list-files-sub-directories-directory/
struct dirent *vaultsDirectoryEntry; struct dirent *vaultsDirectoryEntry;
DIR *vaultsDirectory = opendir(dirString); DIR *vaultsDirectory = opendir(dirString);
if (vaultsDirectory == NULL) { // opendir returns NULL if couldn't open directory error(vaultsDirectory==NULL, "program", "Could not open directory %s", dirString);
printf("\e[0;31mERROR: Could not open current directory\e[0m\n" );
exit(1); //something is fucked up
}
char **dirsArray = NULL; // will contain all the dirs/vaults char **dirsArray = NULL; // will contain all the dirs/vaults
size_t dirsCount = 0; // we need to count how many dirs there is to always readjust how many memory we alloc size_t dirsCount = 0; // we need to count how many dirs there is to always readjust how many memory we alloc
// Refer https://pubs.opengroup.org/onlinepubs/7990989775/xsh/readdir.html // Refer https://pubs.opengroup.org/onlinepubs/7990989775/xsh/readdir.html
// for readdir() // for readdir()
if (debug) {printf("┌------------------------------\n\e[0;32m[DEBUG]\e[0m Files and dirs from the directory\n");} if (shouldDebug) {printf("┌------------------------------\n\e[0;32m[DEBUG]\e[0m Files and dirs from the directory\n");}
debug("┌------------------------------\n Detected files and dirs from the directory:");
while ((vaultsDirectoryEntry = readdir(vaultsDirectory)) != NULL) { while ((vaultsDirectoryEntry = readdir(vaultsDirectory)) != NULL) {
if (debug) {printf("%s\n", vaultsDirectoryEntry->d_name);} // debugs every file/directory altDebug("%s\n", vaultsDirectoryEntry->d_name);
if (vaultsDirectoryEntry->d_name[0] != '.') { // if the entry don't start with a dot (so hidden dirs and hidden files) if (vaultsDirectoryEntry->d_name[0] != '.') { // if the entry don't start with a dot (so hidden dirs and hidden files)
char fullPathEntry[PATH_MAX]; // creates a string of size of the maximum path lenght char fullPathEntry[PATH_MAX]; // creates a string of size of the maximum path lenght
snprintf(fullPathEntry, sizeof(fullPathEntry), "%s/%s", dirString, vaultsDirectoryEntry->d_name); // sets the full absolute path to fullPathEntry snprintf(fullPathEntry, sizeof(fullPathEntry), "%s/%s", dirString, vaultsDirectoryEntry->d_name); // sets the full absolute path to fullPathEntry
@@ -109,7 +145,7 @@ char** getVaultsFromDirectory(char *dirString, size_t *count, int debug) {
} }
} }
} }
if (debug) {printf("└------------------------------\n");} altDebug("└------------------------------\n");
// (TODO LATER) Alphabetically sort them // (TODO LATER) Alphabetically sort them
// free's some used memory // free's some used memory
@@ -119,42 +155,44 @@ char** getVaultsFromDirectory(char *dirString, size_t *count, int debug) {
} }
char** getNotesFromVault(char *pathToVault, char *vault, int *count, int debug) { 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) // 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 // (TODO LATER) Check how it handles non .md files
if (debug) {printf("\e[0;32m[DEBUG]\e[0m Opening %s aka the vault\n", vault);}
// originally from https://www.geeksforgeeks.org/c/c-program-list-files-sub-directories-directory/ // originally from https://www.geeksforgeeks.org/c/c-program-list-files-sub-directories-directory/
struct dirent *notesDirectoryEntry; // (TODO LATER) change name of these variables. notesDirectory is dumb as it is the directory of vaults 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]; char tempPath[PATH_MAX];
snprintf(tempPath, sizeof(tempPath), "%s/%s", pathToVault, vault); // sets the full absolute path to fullPathEntry snprintf(tempPath, sizeof(tempPath), "%s/%s", pathToVault, vault); // sets the full absolute path to fullPathEntry
DIR *vaultDirectory = opendir(tempPath); DIR *vaultDirectory = opendir(tempPath);
if (vaultDirectory == NULL) { // opendir returns NULL if couldn't open directory error(vaultDirectory==NULL, "program", "Could not open directory %s", tempPath);
printf("\e[0;31mERROR: Could not open current directory\e[0m\n" );
exit(1); //something is fucked up
}
char **notesArray = NULL; // will contain all the notes 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 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 // Refer https://pubs.opengroup.org/onlinepubs/7990989775/xsh/readdir.html
// for readdir() // for readdir()
if (debug) {printf("┌------------------------------\n\e[0;32m[DEBUG]\e[0m Files and dirs from the vault:\n");} debug("┌------------------------------\nDetected Files and dirs from the vault:");
while ((notesDirectoryEntry = readdir(vaultDirectory)) != NULL) { while ((vaultEntry = readdir(vaultDirectory)) != NULL) {
if (debug) {printf("%s\n", notesDirectoryEntry->d_name);} altDebug("%s ", vaultEntry->d_name);
// for the regex code https://stackoverflow.com/a/1085120
if (notesDirectoryEntry->d_name[0] != '.') { // if the entry don't start with a dot (so hidden dirs and hidden files) regex_t regex;
int regexReturn;
// compiles the regex
regexReturn = regcomp(&regex, 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 char fullPathEntry[PATH_MAX]; // creates a string of size of the maximum path lenght
snprintf(fullPathEntry, sizeof(fullPathEntry), "%s/%s/%s", pathToVault, vault, notesDirectoryEntry->d_name); // sets the full absolute path to fullPathEntry 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(&regex, vaultEntry->d_name, 0, NULL, 0);
struct stat metadataPathEntry; struct stat metadataPathEntry;
if (stat(fullPathEntry, &metadataPathEntry) == 0 && !S_ISDIR(metadataPathEntry.st_mode)) { // if this entry is a file 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 = realloc(notesArray, (notesCount + 1)*sizeof(char*)); // resize notesArray so that
notesArray[notesCount] = strdup(notesDirectoryEntry->d_name); // copy the dir name into notesArray notesArray[notesCount] = strdup(vaultEntry->d_name); // copy the dir name into notesArray
notesCount++; 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");}
} }
if (debug) {printf("└ ------------------------------\n");} altDebug("└ ------------------------------\n");
// (TODO LATER) Alphabetically sort them // (TODO LATER) Alphabetically sort them
// free's some used memory // free's some used memory
closedir(vaultDirectory); closedir(vaultDirectory);
@@ -162,68 +200,104 @@ char** getNotesFromVault(char *pathToVault, char *vault, int *count, int debug)
return notesArray; return notesArray;
} }
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(&regex, 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(&regex, 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;
}
int openEditor(char *path, char *editor, int render, int endOfFile, int debug) {
int openEditor(char *path, char *editor, int render, int endOfFile, int shouldDebug) {
// (TODO LATER) Bug app breaks if browser was not already launched before vivify
// (TODO LATER) find better name for endOfFile // (TODO LATER) find better name for endOfFile
//(TODO LATER) for nvim and vim we should check if there is swap files or recovery files and handle that //(TODO LATER) for nvim and vim we should check if there is swap files or recovery files and handle that
pid_t pid = fork(); // this forking allows the programs to return when nvim is closed pid_t pid = fork(); // this forking allows the programs to return when nvim is closed
if (pid < 0) { error(pid<0, "program", "fork() failed.");
perror("\e[0;31mERROR: fork failed\e[0m\n"); if (pid == 0) {
return 1;
} else if (pid == 0) {
// Child process: replace with editor of choice // Child process: replace with editor of choice
if (strcmp(editor, "neovim") == 0) { // opens with Neovim if (strcmp(editor, "neovim") == 0) { // opens with Neovim
//(TODO LATER) we should (with a config option) append a new line every time it opens //(TODO LATER) we should (with a config option) append a new line every time it opens
if (render) { // don't render using vivify if (render) { // don't render using vivify
if (endOfFile) { // goes to the end of the file on opening. (TODO LATER) find a better way to do this loops. Maybe an array of args and if () we add the arg to the array and we pass the whole array to execlp if (endOfFile) { // goes to the end of the file on opening. (TODO LATER) find a better way to do this loops. Maybe an array of args and if () we add the arg to the array and we pass the whole array to execlp
if (debug) {printf("\e[0;32m[DEBUG]\e[0m Opening with command:\nnvim +:$ +:Vivify %s\n", path);} // :$ goes to the end of the file. :Vivify runs vivify // :$ goes to the end of the file. :Vivify runs vivify
execlp("nvim", "nvim", "+:$", "+:Vivify", path, NULL); debug("Running nvim +:$ +:Vivify %s", path);
perror("\e[0;31mERROR: execlp failed. Nvim might be not installed or not in path.\e[0m\n"); execlp("nvim", "nvim", "+:$", "+:Vivify", path, NULL);
exit(1); // (TODO LATER) This exist only if error or everytime. If it does every time change to exit(0); error(1, "program", "execlp() failed."); // if something after execlp is executed it means something failed. Normally this function is not called
} else { // don't go to the end of the file } else { // don't go to the end of the file
if (debug) {printf("\e[0;32m[DEBUG]\e[0m Opening with command:\nnvim +:Vivify %s\n", path);} debug("Running nvim +:Vivify %s", path);
execlp("nvim", "nvim", "+:Vivify", path, NULL); execlp("nvim", "nvim", "+:Vivify", path, NULL);
perror("\e[0;31mERROR: execlp failed. Nvim might be not installed or not in path.\e[0m\n"); error(1, "program", "execlp() failed.");
exit(1);
} }
} else { // don't render using vivify } else { // don't render using vivify
if (endOfFile) { // go to end of the file on opening if (endOfFile) { // go to end of the file on opening
if (debug) {printf("\e[0;32m[DEBUG]\e[0m Opening with command:\nnvim +:$ %s\n", path);} debug("Running nvim +:$ %s", path);
execlp("nvim", "nvim", "+:$", path, NULL); execlp("nvim", "nvim", "+:$", path, NULL);
perror("\e[0;31mERROR: execlp failed. Nvim might be not installed or not in path.\e[0m\n"); error(1, "program", "execlp() failed.");
exit(1);
} else { // don't go to the end of the file on opening } else { // don't go to the end of the file on opening
if (debug) {printf("\e[0;32m[DEBUG]\e[0m Opening with command:\nnvim %s\n", path);} debug("Running nvim %s", path);
execlp("nvim", "nvim", path, NULL); execlp("nvim", "nvim", path, NULL);
perror("\e[0;31mERROR: execlp failed. Nvim might be not installed or not in path.\e[0m\n"); error(1, "program", "execlp() failed.");
exit(1);
} }
} }
} else if (strcmp(editor, "vim") == 0) { // opens with Vim // see comments for neovim for explanations } else if (strcmp(editor, "vim") == 0) { // opens with Vim // see comments for neovim for explanations
//(TODO LATER) we should (with a config option) append a new line every time it opens //(TODO LATER) we should (with a config option) append a new line every time it opens
if (render) { if (render) {
if (endOfFile) { if (endOfFile) {
if (debug) {printf("\e[0;32m[DEBUG]\e[0m Opening with command:\nvim +:$ +:Vivify %s\n", path);} debug("Running vim +:$ +:Vivify %s", path);
execlp("vim", "vim", "+:$", "+:Vivify", path, NULL); execlp("vim", "vim", "+:$", "+:Vivify", path, NULL);
perror("\e[0;31mERROR: execlp failed. Vim might be not installed or not in path.\e[0m\n"); error(1, "program", "execlp() failed.");
exit(1);
} else { } else {
if (debug) {printf("\e[0;32m[DEBUG]\e[0m Opening with command:\nvim +:Vivify %s\n", path);} debug("Running vim +:Vivify %s", path);
execlp("vim", "vim", "+:Vivify", path, NULL); execlp("vim", "vim", "+:Vivify", path, NULL);
perror("\e[0;31mERROR: execlp failed. Vim might be not installed or not in path.\e[0m\n"); error(1, "program", "execlp() failed.");
exit(1);
} }
} else { } else {
if (endOfFile) { if (endOfFile) {
if (debug) {printf("\e[0;32m[DEBUG]\e[0m Opening with command:\nvim +:$ %s\n", path);} debug("Running vim +:$ %s", path);
execlp("vim", "vim", "+:$", path, NULL); execlp("vim", "vim", "+:$", path, NULL);
perror("\e[0;31mERROR: execlp failed. Vim might be not installed or not in path.\e[0m\n"); error(1, "program", "execlp() failed.");
exit(1);
} else { } else {
if (debug) {printf("\e[0;32m[DEBUG]\e[0m Opening with command:\nvim %s\n", path);} debug("Running vim %s", path);
execlp("vim", "vim", path, NULL); execlp("vim", "vim", path, NULL);
perror("\e[0;31mERROR: execlp failed. Vim might be not installed or not in path.\e[0m\n"); error(1, "program", "execlp() failed.");
exit(1);
} }
} }
} }
+21 -3
View File
@@ -14,9 +14,15 @@
#include <sys/wait.h> #include <sys/wait.h>
#include <limits.h> #include <limits.h>
#include <cjson/cJSON.h> #include <cjson/cJSON.h>
#include <regex.h>
#include <errno.h>
#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 HASH_MACRO "0ea1d20bcdd52c46c086d3dba125b9b83ad8cbea2e026d5646775f48bae8f867" // if the user inputs this hash. The program brokes. It was the best way i found to see if some values were unchanged #define HASH_MACRO "0ea1d20bcdd52c46c086d3dba125b9b83ad8cbea2e026d5646775f48bae8f867" // if the user inputs this hash. The program brokes. It was the best way i found to see if some values were unchanged
// you must edit this two values if you want to add suport for an editor // 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 char *supportedEditor[]; // array of supported editors
extern const int numEditors; // number of supported editors extern const int numEditors; // number of supported editors
@@ -27,6 +33,13 @@ int compareString(const void *a, const void *b);
int doesEditorExist(char *editorToCheck, int debug); int doesEditorExist(char *editorToCheck, int debug);
// this basically checks all the dirs from your path for the editor. This is a safety check // this basically checks all the dirs from your path for the editor. This is a safety check
// If the executable from an editor is not the editor name (for example neovim and nvim), you must handle at the start of the function. // If the executable from an editor is not the editor name (for example neovim and nvim), you must handle at the start of the function.
void _debug(const int d, const char *file, const int line, const char *function, const char *message, ...);
//formated debugging
void _altDebug(const int d, const char *message, ...);
//use for less formal debuggin. (usefull if enumerating or making a list)
void _error(const int shouldDebug, const int condition, const char *type, const char *file, const int line, const char *function, const char *message, ...);
// formated error
// if the error is not a critical one (for ex: file not found) System error message will be Succesfull
int isStringInArray(const char *string, const char **array, const int len); 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
@@ -38,8 +51,13 @@ int rmrf(char *path);
//deletes an entire directory. Use with parsimony and carefullness //deletes an entire directory. Use with parsimony and carefullness
char **getVaultsFromDirectory(char *dirString, size_t *count, int debug); char **getVaultsFromDirectory(char *dirString, size_t *count, int debug);
// 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
char **getNotesFromVault(char *pathToVault, char *vault, int *count, int debug); 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) // 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
// 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
int openEditor(char *path, char *editor, int render, int endOfFile, int debug); int openEditor(char *path, char *editor, int render, int endOfFile, int debug);
// Inputs are the path to the file, the editor to open and some rendering option // Inputs are the path to the file, the editor to open and some rendering option
// render: if we render the .md file with Vivify // render: if we render the .md file with Vivify