mirror of
https://github.com/tomasriveral/NoteWrapper.git
synced 2026-08-12 02:18:38 +02:00
Added first part of journal code and debug(), altDebug() and error()
This commit is contained in:
+153
-79
@@ -3,13 +3,56 @@
|
||||
const char *supportedEditor[] = {"neovim", "vim"};
|
||||
const int numEditors = 2;
|
||||
|
||||
//(TODO LATER) We should write a debug() function and an error(function)
|
||||
|
||||
int compareString(const void *a, const void *b) {
|
||||
const char *str1 = *(const char **)a;
|
||||
const char *str2 = *(const char **)b;
|
||||
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;
|
||||
if (strcmp(editorToCheck, "neovim") == 0) {
|
||||
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);
|
||||
}
|
||||
char *path_env = getenv("PATH");
|
||||
if (!path_env) {
|
||||
printf("\e[0;31mERROR: getenv(\"PATH\") failed to get your path. NoteWrapper is unable to check if your desired editor is installed\n");
|
||||
exit(1);
|
||||
};
|
||||
if (debug) {printf("\e[0;32m[DEBUG]\e[0m Your PATH is %s\n", 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");
|
||||
debug("Your PATH is %s", path_env);
|
||||
char *paths = strdup(path_env); // duplicate because strtok modifies the string
|
||||
char *dir = strtok(paths, ":");
|
||||
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
|
||||
// (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 rv = remove(fpath);
|
||||
|
||||
if (rv)
|
||||
perror(fpath);
|
||||
|
||||
return rv;
|
||||
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);
|
||||
error(rv, "program", "remove() failed to delete %s", fpath);
|
||||
return rv;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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) 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
|
||||
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/
|
||||
struct dirent *vaultsDirectoryEntry;
|
||||
DIR *vaultsDirectory = opendir(dirString);
|
||||
if (vaultsDirectory == NULL) { // opendir returns NULL if couldn't open directory
|
||||
printf("\e[0;31mERROR: Could not open current directory\e[0m\n" );
|
||||
exit(1); //something is fucked up
|
||||
}
|
||||
error(vaultsDirectory==NULL, "program", "Could not open directory %s", dirString);
|
||||
char **dirsArray = NULL; // will contain all the dirs/vaults
|
||||
size_t dirsCount = 0; // we need to count how many dirs there is to always readjust how many memory we alloc
|
||||
// Refer https://pubs.opengroup.org/onlinepubs/7990989775/xsh/readdir.html
|
||||
// for readdir()
|
||||
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) {
|
||||
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)
|
||||
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
|
||||
@@ -109,7 +145,7 @@ char** getVaultsFromDirectory(char *dirString, size_t *count, int debug) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (debug) {printf("└------------------------------\n");}
|
||||
altDebug("└------------------------------\n");
|
||||
// (TODO LATER) Alphabetically sort them
|
||||
|
||||
// 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)
|
||||
// (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/
|
||||
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];
|
||||
snprintf(tempPath, sizeof(tempPath), "%s/%s", pathToVault, vault); // sets the full absolute path to fullPathEntry
|
||||
DIR *vaultDirectory = opendir(tempPath);
|
||||
if (vaultDirectory == NULL) { // opendir returns NULL if couldn't open directory
|
||||
printf("\e[0;31mERROR: Could not open current directory\e[0m\n" );
|
||||
exit(1); //something is fucked up
|
||||
}
|
||||
error(vaultDirectory==NULL, "program", "Could not open directory %s", tempPath);
|
||||
char **notesArray = NULL; // will contain all the notes
|
||||
size_t notesCount = 0; // we need to count how many notes there is to always readjust how many memory we alloc
|
||||
// Refer https://pubs.opengroup.org/onlinepubs/7990989775/xsh/readdir.html
|
||||
// for readdir()
|
||||
if (debug) {printf("┌------------------------------\n\e[0;32m[DEBUG]\e[0m Files and dirs from the vault:\n");}
|
||||
while ((notesDirectoryEntry = readdir(vaultDirectory)) != NULL) {
|
||||
debug("┌------------------------------\nDetected Files and dirs from the vault:");
|
||||
while ((vaultEntry = readdir(vaultDirectory)) != NULL) {
|
||||
|
||||
if (debug) {printf("%s\n", notesDirectoryEntry->d_name);}
|
||||
|
||||
if (notesDirectoryEntry->d_name[0] != '.') { // if the entry don't start with a dot (so hidden dirs and hidden files)
|
||||
altDebug("%s ", vaultEntry->d_name);
|
||||
// for the regex code https://stackoverflow.com/a/1085120
|
||||
regex_t regex;
|
||||
int regexReturn;
|
||||
// compiles the regex
|
||||
regexReturn = regcomp(®ex, journalRegex, 0);
|
||||
if (vaultEntry->d_name[0] != '.') { // if the entry don't start with a dot (so hidden dirs and hidden files)
|
||||
char fullPathEntry[PATH_MAX]; // creates a string of size of the maximum path lenght
|
||||
snprintf(fullPathEntry, sizeof(fullPathEntry), "%s/%s/%s", pathToVault, vault, 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(®ex, vaultEntry->d_name, 0, NULL, 0);
|
||||
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[notesCount] = strdup(notesDirectoryEntry->d_name); // copy the dir name into notesArray
|
||||
notesArray[notesCount] = strdup(vaultEntry->d_name); // copy the dir name into notesArray
|
||||
notesCount++;
|
||||
}
|
||||
}
|
||||
altDebug("did not match with the regex. It is a note.\n");
|
||||
} else if (!regexReturn) {altDebug("matched with the regex. It is a journal.\n");}
|
||||
} else {altDebug("was ignored\n");}
|
||||
}
|
||||
if (debug) {printf("└ ------------------------------\n");}
|
||||
altDebug("└ ------------------------------\n");
|
||||
// (TODO LATER) Alphabetically sort them
|
||||
// free's some used memory
|
||||
closedir(vaultDirectory);
|
||||
@@ -162,68 +200,104 @@ char** getNotesFromVault(char *pathToVault, char *vault, int *count, int debug)
|
||||
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(®ex, journalRegex, 0);
|
||||
error(regexReturn, "program", "Regex could not compile. Perhaps there is an error with the regex string");
|
||||
debug("Regex compiled succesfully");
|
||||
// Refer https://pubs.opengroup.org/onlinepubs/7990989775/xsh/readdir.html
|
||||
// for readdir()
|
||||
debug("┌------------------------------------------\nDetected files and dirs from the vault");
|
||||
while ((vaultEntry = readdir(vaultDirectory)) != NULL) { // we iterate over every entry from the dir. So files and dirs (. and .. included)
|
||||
altDebug("%s ", vaultEntry->d_name);
|
||||
if (vaultEntry->d_name[0] != '.') { // if the entry don't start with a dot (so hidden dirs and hidden files)
|
||||
regexReturn = regexec(®ex, vaultEntry->d_name, 0, NULL, 0);
|
||||
if (!regexReturn) { // if the regex matches
|
||||
altDebug("matched with the regex. It is a journal.\n");
|
||||
journalsArray = realloc(journalsArray, (journalsCount + 1)*sizeof(char*)); // resize notesArray so that
|
||||
journalsArray[journalsCount] = strdup(vaultEntry->d_name); // copy the dir name into notesArray
|
||||
journalsCount++;
|
||||
} else {
|
||||
altDebug("did not matched with the regex. It is a note.\n");
|
||||
}
|
||||
} else {
|
||||
altDebug(" was ignored\n");
|
||||
}
|
||||
}
|
||||
altDebug("└ ------------------------------\n");
|
||||
// free's some used memory
|
||||
closedir(vaultDirectory);
|
||||
*count = journalsCount; // passes the number of files
|
||||
return journalsArray;
|
||||
}
|
||||
|
||||
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) 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
|
||||
if (pid < 0) {
|
||||
perror("\e[0;31mERROR: fork failed\e[0m\n");
|
||||
return 1;
|
||||
} else if (pid == 0) {
|
||||
error(pid<0, "program", "fork() failed.");
|
||||
if (pid == 0) {
|
||||
// Child process: replace with editor of choice
|
||||
if (strcmp(editor, "neovim") == 0) { // opens with Neovim
|
||||
//(TODO LATER) we should (with a config option) append a new line every time it opens
|
||||
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 (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
|
||||
execlp("nvim", "nvim", "+:$", "+:Vivify", path, NULL);
|
||||
perror("\e[0;31mERROR: execlp failed. Nvim might be not installed or not in path.\e[0m\n");
|
||||
exit(1); // (TODO LATER) This exist only if error or everytime. If it does every time change to exit(0);
|
||||
// :$ goes to the end of the file. :Vivify runs vivify
|
||||
debug("Running nvim +:$ +:Vivify %s", path);
|
||||
execlp("nvim", "nvim", "+:$", "+:Vivify", path, NULL);
|
||||
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
|
||||
if (debug) {printf("\e[0;32m[DEBUG]\e[0m Opening with command:\nnvim +:Vivify %s\n", path);}
|
||||
execlp("nvim", "nvim", "+:Vivify", path, NULL);
|
||||
perror("\e[0;31mERROR: execlp failed. Nvim might be not installed or not in path.\e[0m\n");
|
||||
exit(1);
|
||||
debug("Running nvim +:Vivify %s", path);
|
||||
execlp("nvim", "nvim", "+:Vivify", path, NULL);
|
||||
error(1, "program", "execlp() failed.");
|
||||
}
|
||||
} else { // don't render using vivify
|
||||
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);}
|
||||
execlp("nvim", "nvim", "+:$", path, NULL);
|
||||
perror("\e[0;31mERROR: execlp failed. Nvim might be not installed or not in path.\e[0m\n");
|
||||
exit(1);
|
||||
debug("Running nvim +:$ %s", path);
|
||||
execlp("nvim", "nvim", "+:$", path, NULL);
|
||||
error(1, "program", "execlp() failed.");
|
||||
} 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);}
|
||||
execlp("nvim", "nvim", path, NULL);
|
||||
perror("\e[0;31mERROR: execlp failed. Nvim might be not installed or not in path.\e[0m\n");
|
||||
exit(1);
|
||||
debug("Running nvim %s", path);
|
||||
execlp("nvim", "nvim", path, NULL);
|
||||
error(1, "program", "execlp() failed.");
|
||||
}
|
||||
}
|
||||
} 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
|
||||
if (render) {
|
||||
if (endOfFile) {
|
||||
if (debug) {printf("\e[0;32m[DEBUG]\e[0m Opening with command:\nvim +:$ +:Vivify %s\n", path);}
|
||||
execlp("vim", "vim", "+:$", "+:Vivify", path, NULL);
|
||||
perror("\e[0;31mERROR: execlp failed. Vim might be not installed or not in path.\e[0m\n");
|
||||
exit(1);
|
||||
debug("Running vim +:$ +:Vivify %s", path);
|
||||
execlp("vim", "vim", "+:$", "+:Vivify", path, NULL);
|
||||
error(1, "program", "execlp() failed.");
|
||||
} else {
|
||||
if (debug) {printf("\e[0;32m[DEBUG]\e[0m Opening with command:\nvim +:Vivify %s\n", path);}
|
||||
execlp("vim", "vim", "+:Vivify", path, NULL);
|
||||
perror("\e[0;31mERROR: execlp failed. Vim might be not installed or not in path.\e[0m\n");
|
||||
exit(1);
|
||||
debug("Running vim +:Vivify %s", path);
|
||||
execlp("vim", "vim", "+:Vivify", path, NULL);
|
||||
error(1, "program", "execlp() failed.");
|
||||
}
|
||||
} else {
|
||||
if (endOfFile) {
|
||||
if (debug) {printf("\e[0;32m[DEBUG]\e[0m Opening with command:\nvim +:$ %s\n", path);}
|
||||
execlp("vim", "vim", "+:$", path, NULL);
|
||||
perror("\e[0;31mERROR: execlp failed. Vim might be not installed or not in path.\e[0m\n");
|
||||
exit(1);
|
||||
debug("Running vim +:$ %s", path);
|
||||
execlp("vim", "vim", "+:$", path, NULL);
|
||||
error(1, "program", "execlp() failed.");
|
||||
} else {
|
||||
if (debug) {printf("\e[0;32m[DEBUG]\e[0m Opening with command:\nvim %s\n", path);}
|
||||
execlp("vim", "vim", path, NULL);
|
||||
perror("\e[0;31mERROR: execlp failed. Vim might be not installed or not in path.\e[0m\n");
|
||||
exit(1);
|
||||
debug("Running vim %s", path);
|
||||
execlp("vim", "vim", path, NULL);
|
||||
error(1, "program", "execlp() failed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user