mirror of
https://github.com/tomasriveral/NoteWrapper.git
synced 2026-08-11 18:18:36 +02:00
Added divided journals
This commit is contained in:
@@ -36,7 +36,8 @@ Change `$/.config/notewrapper/config.json`. If it does not exist. On building, i
|
||||
- [x] Port vivify.vim to nixpkgs
|
||||
- [ ] Add a way to have vaults in different directories
|
||||
- [x] Actually open vivify when opening nvim
|
||||
- [ ] Write the journaling code (separate files or one big journal files)
|
||||
- [x] Write the journaling code (separate files or one big journal files)
|
||||
- [ ] Adapt createNewNote with journals
|
||||
- [ ] Automatic backups
|
||||
- [x] Add flags for customization
|
||||
- [ ] Write a good README.md
|
||||
|
||||
+4
-4
@@ -210,8 +210,8 @@ int main(int argc, char *argv[]) {
|
||||
vaultSelected = bypassVaultSelection;
|
||||
goto note_selection;
|
||||
}
|
||||
vaultSelected = ncursesSelect(vaultsArray, "Select vault (Use arrows or WASD, Enter to select):", vaultsCount, extraOptions, shouldDebug);
|
||||
|
||||
vaultSelected = ncursesSelect(vaultsArray, "vault", 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
|
||||
@@ -264,7 +264,7 @@ note_selection:
|
||||
goto note_creation;
|
||||
}
|
||||
}
|
||||
noteSelected = ncursesSelect(filesArray, "Select note or journal (Use arrows or WASD, Enter to select):", filesCount, extraNotesOptions, shouldDebug);
|
||||
noteSelected = ncursesSelect(filesArray, "note or journal", 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
|
||||
@@ -306,7 +306,7 @@ note_creation:
|
||||
shouldChangeVault = 1;
|
||||
} else if (strcmp(noteSelected, "Delete vault") == 0) {
|
||||
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, shouldDebug);
|
||||
char *answer = ncursesSelect((char **)yesNo, "Are you sure you want to delete the entire vault? This can not be undone.", 1, 1, " ", "", "", shouldDebug); // (TODO LATER) This is ugly with Select Are you sure[...]
|
||||
debug("You answered: %s for deleting the vault %s", answer, vaultSelected);
|
||||
if (strcmp(answer, "Yes.") == 0) {
|
||||
// delete the vault after confirmation by the user
|
||||
|
||||
+69
-3
@@ -135,7 +135,10 @@ char *updateJournal(char *path, char *journal, char *timeFormat, int shouldDebug
|
||||
|
||||
char *date = getFormatedTime(timeFormat, shouldDebug);
|
||||
debug("Formated time for the journal's entry is %s", date);
|
||||
|
||||
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);
|
||||
struct stat metadata;
|
||||
error(stat(path, &metadata), "program", "stat() failed to get information about %s", path);
|
||||
if (S_ISREG(metadata.st_mode)) {
|
||||
@@ -144,10 +147,73 @@ char *updateJournal(char *path, char *journal, char *timeFormat, int shouldDebug
|
||||
appendToFile(path, date, shouldDebug);
|
||||
} // if there is an entry do nothing
|
||||
} else if (S_ISDIR(metadata.st_mode)) {
|
||||
debug("%s is a divided journal.", path);
|
||||
|
||||
debug("%s is a divided journal.", path);
|
||||
struct dirent *dividedJournalEntry;
|
||||
// snprintf does not like to have the same variable as input and output so we use a buffer
|
||||
char temp[PATH_MAX];
|
||||
snprintf(temp, PATH_MAX, "%s/", path); // appends a /. For safety
|
||||
strncpy(path, temp, PATH_MAX);
|
||||
DIR *dividedJournalDirectory = opendir(path);
|
||||
error(dividedJournalDirectory==NULL, "program", "Could not open directory %s", path);
|
||||
char **entryArray = NULL; // will contain all the entries of the divided journal
|
||||
// This time it will be different. We must add "invert" the extraOptions to the options so that the Create new entry in journal is on top
|
||||
entryArray = realloc(entryArray, sizeof(char*));
|
||||
char *createEntryMessage = malloc(PATH_MAX);
|
||||
snprintf(createEntryMessage, PATH_MAX, "Create new entry for the journal %s", journal);
|
||||
entryArray[0] = createEntryMessage;
|
||||
size_t entryCount = 1; // 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()
|
||||
debug("┌------------------------------\n Detected files and dirs from %s:", path);
|
||||
// iterates over all the entries from the dir
|
||||
while ((dividedJournalEntry = readdir(dividedJournalDirectory)) != NULL) {
|
||||
// (TODO LATER) find a way to sort them
|
||||
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
|
||||
|
||||
struct stat metadataPathEntry;
|
||||
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
|
||||
entryCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
altDebug("└------------------------------\n");
|
||||
// free's some used memory
|
||||
closedir(dividedJournalDirectory);
|
||||
// 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:", 1, entryCount -1, " ", " ", "", 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);
|
||||
snprintf(temp, PATH_MAX, "%s/%s", path, dateWithExtension);
|
||||
strncpy(path, temp, PATH_MAX);
|
||||
if (!isStringInArray(date, (const char **)entryArray, entryCount)) { // it only creates it if it doesn't already exist
|
||||
// if it does exist it will just pass the full path
|
||||
|
||||
debug("Creating entry %s inside %s", date, path);
|
||||
FILE *file;
|
||||
file = fopen(path, "w");
|
||||
error(file == NULL, "program", "%s couldn't be created", path);
|
||||
debug("Writing %s\\n to %s", date, path);
|
||||
fprintf(file, "%s\n", date);
|
||||
fclose(file);
|
||||
}
|
||||
} else { // we just recreate the path to the selected entry
|
||||
// snprintf does not like to have the same variable as input and output so we use a buffer
|
||||
char temp[PATH_MAX];
|
||||
snprintf(temp, PATH_MAX, "%s/%s", path, selectedOption);
|
||||
strncpy(path, temp, PATH_MAX);
|
||||
debug("Returning path to the selected entry: %s", path);
|
||||
}
|
||||
// (TODO LATER) free all unused entryArray[i]
|
||||
} else {
|
||||
error(1, "program", "%s is not a file and not a directory.", path);
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ char *createNewNote(char dirToVault[PATH_MAX], char *vaultFromDir, char *bypass,
|
||||
return fileFullPath;
|
||||
}
|
||||
|
||||
char* ncursesSelect(char **options, char *optionsText, size_t optionsNumber, size_t extraOptionsNumber, int shouldDebug) {
|
||||
char* ncursesSelect(char **options, char *optionsText, size_t optionsNumber, size_t extraOptionsNumber, char *bottomText, char *middleText, char *topText, int shouldDebug) {
|
||||
int highlight = 0; //curently highlighted option
|
||||
int key;
|
||||
|
||||
@@ -104,29 +104,41 @@ char* ncursesSelect(char **options, char *optionsText, size_t optionsNumber, siz
|
||||
clear();
|
||||
attron(COLOR_PAIR(1));
|
||||
mvprintw(0,0, "Select %s (Use arrows or WASD, Enter to select):", optionsText);
|
||||
int offset = 1;
|
||||
if (strcmp(bottomText, "") != 0) {
|
||||
mvprintw(offset, 1, "%s", bottomText);
|
||||
offset++;
|
||||
}
|
||||
// Print options with highlighting
|
||||
for (int i = 0; i < optionsNumber; i++) {
|
||||
if (i == highlight) {
|
||||
attron(A_REVERSE);
|
||||
} // highlight selected
|
||||
mvprintw(i+2, 2, "%s", options[i]);
|
||||
mvprintw(i+offset, 2, "%s", options[i]);
|
||||
if (i == highlight) {
|
||||
attroff(A_REVERSE);
|
||||
}
|
||||
}
|
||||
attroff(COLOR_PAIR(1));
|
||||
if (strcmp(middleText, "") != 0) {
|
||||
mvprintw(offset+optionsNumber, 1, "%s", middleText);
|
||||
offset++;
|
||||
}
|
||||
// Printf extraOptions with highlighting
|
||||
attron(COLOR_PAIR(2));
|
||||
for (int k = optionsNumber; k < optionsNumber + extraOptionsNumber; k++) {
|
||||
if (k == highlight) {
|
||||
attron(A_REVERSE);
|
||||
}
|
||||
mvprintw(k+2, 2, "%s", options[k]);
|
||||
mvprintw(k+offset, 2, "%s", options[k]);
|
||||
if (k == highlight) {
|
||||
attroff(A_REVERSE);
|
||||
}
|
||||
}
|
||||
attroff(COLOR_PAIR(2));
|
||||
attron(COLOR_PAIR(1));
|
||||
mvprintw(offset+optionsNumber+extraOptionsNumber, 1, "%s", topText);
|
||||
attroff(COLOR_PAIR(1));
|
||||
key = getch(); //get some int which value correspond to some key being pressed
|
||||
|
||||
switch(key) {
|
||||
|
||||
@@ -20,7 +20,7 @@ void createNewVault(char *dirToVault, int debug);
|
||||
// Creates a new vault with this input
|
||||
// If vault already exists, prints a warning
|
||||
// returns nothing
|
||||
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, char *bottomText, char *middleText, char *topText, int debug);
|
||||
// this function is used multiple times let the user select one options from many with ncurses in a TUI.
|
||||
// options is the array of strings with all the options.
|
||||
// optionsText is the text that will be printed at the top (For example: "Please select ...")
|
||||
@@ -28,5 +28,9 @@ char* ncursesSelect(char **options, char *optionsText, size_t optionsNumber, siz
|
||||
// options could be the list of all notes or all vaults
|
||||
// extraOptions are options that are special and have a special color (for ex: "Delete vault", "Settings", etc.)
|
||||
// note: extraOptions should be at the end of options
|
||||
// topText is printed between 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
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user