mirror of
https://github.com/tomasriveral/NoteWrapper.git
synced 2026-08-12 10:20:46 +02:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
36767b188d |
@@ -48,7 +48,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
gh pr create \
|
gh pr create \
|
||||||
--base main \
|
--base main \
|
||||||
--head release/${{ inputs.version }} \
|
--head release/v${{ inputs.version }} \
|
||||||
--title "[Automatic] Release PR ${{ inputs.version }}" \
|
--title "[Automatic] Release PR ${{ inputs.version }}" \
|
||||||
--body "Automated release PR.\nAfter the test's succesfull run, create manually a release with a new tag matching ${{ inputs.version }}"
|
--body "Automated release PR.\nAfter the test's succesfull run, create manually a release with a new tag matching ${{ inputs.version }}"
|
||||||
env:
|
env:
|
||||||
|
|||||||
Generated
+18
-1
@@ -34,10 +34,27 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"notewrapper": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1779789213,
|
||||||
|
"narHash": "sha256-N+5RH2qF5VdBmfIdxRhg7DceH7ALAie+kFOR7xL1pDs=",
|
||||||
|
"owner": "tomasriveral",
|
||||||
|
"repo": "NoteWrapper",
|
||||||
|
"rev": "f7c84136a5ff4a0712b31cbb41ce3e1dd7fde8d3",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "tomasriveral",
|
||||||
|
"repo": "NoteWrapper",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-utils": "flake-utils",
|
"flake-utils": "flake-utils",
|
||||||
"nixpkgs": "nixpkgs"
|
"nixpkgs": "nixpkgs",
|
||||||
|
"notewrapper": "notewrapper"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"systems": {
|
"systems": {
|
||||||
|
|||||||
@@ -4,18 +4,22 @@
|
|||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
flake-utils.url = "github:numtide/flake-utils";
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
|
notewrapper = {
|
||||||
|
url = "github:tomasriveral/NoteWrapper";
|
||||||
|
flake = false;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = { self, nixpkgs, flake-utils}:
|
outputs = { self, nixpkgs, flake-utils, notewrapper }:
|
||||||
flake-utils.lib.eachDefaultSystem (system:
|
flake-utils.lib.eachDefaultSystem (system:
|
||||||
let
|
let
|
||||||
pkgs = import nixpkgs { inherit system; };
|
pkgs = import nixpkgs { inherit system; };
|
||||||
in {
|
in {
|
||||||
packages.default = pkgs.stdenv.mkDerivation (finalAttrs: {
|
packages.default = pkgs.stdenv.mkDerivation (finalAttrs: {
|
||||||
pname = "notewrapper";
|
pname = "notewrapper";
|
||||||
version = "v2.2";
|
version = "v2.1.1";
|
||||||
|
|
||||||
src = ./.;
|
src = notewrapper;
|
||||||
|
|
||||||
nativeBuildInputs = with pkgs; [
|
nativeBuildInputs = with pkgs; [
|
||||||
pkg-config
|
pkg-config
|
||||||
|
|||||||
+14
-46
@@ -529,14 +529,9 @@ backup_config_end:
|
|||||||
shouldDebug); // check if editor is supported and if it is installed. If not, it
|
shouldDebug); // check if editor is supported and if it is installed. If not, it
|
||||||
// will throw an error.
|
// will throw an error.
|
||||||
|
|
||||||
int *backupMessage = malloc(sizeof(int)); // Used later to set the backuping message.
|
|
||||||
*backupMessage = 0; // default don't show the message
|
|
||||||
int forceBackup = 0;
|
|
||||||
if (doesBackup) {
|
if (doesBackup) {
|
||||||
debug("Handling normal backup");
|
debug("Handling backup");
|
||||||
forceBackup = 0;
|
handleBackups(directoriesArray, numDirectories, backupDirectoriesArray, homedir, interval, (const char **)rsyncArgs, rsyncArgsNumber, shouldDebug);
|
||||||
handleBackups(directoriesArray, numDirectories, backupDirectoriesArray, homedir, interval, (const char **)rsyncArgs, rsyncArgsNumber, forceBackup, backupMessage, shouldDebug);
|
|
||||||
debug("backupMessage was set to %d by a normal backup", *backupMessage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
initscr(); // initialize ncurses
|
initscr(); // initialize ncurses
|
||||||
@@ -577,26 +572,13 @@ backup_config_end:
|
|||||||
}
|
}
|
||||||
altDebug("└ ------------------------------\n");
|
altDebug("└ ------------------------------\n");
|
||||||
}
|
}
|
||||||
int extraOptions = 3;
|
|
||||||
if (doesBackup) {
|
|
||||||
extraOptions++; // space for "Backup now" button
|
|
||||||
}
|
|
||||||
if (*backupMessage) {
|
|
||||||
extraOptions++;
|
|
||||||
}
|
|
||||||
vaultsArray = realloc(vaultsArray, (vaultsCount + extraOptions) * sizeof(char *)); // resize vaultsArray to fit the extra options
|
|
||||||
int index = 0;
|
|
||||||
vaultsArray[vaultsCount + index++] = "Create a new vault"; // some more options that are not vaults
|
|
||||||
vaultsArray[vaultsCount + index++] = "Settings";
|
|
||||||
if (doesBackup) {
|
|
||||||
vaultsArray[vaultsCount + index++] = "Backup now";
|
|
||||||
}
|
|
||||||
vaultsArray[vaultsCount + index++] = "Quit (Ctrl+C)";
|
|
||||||
if (*backupMessage) {
|
|
||||||
vaultsArray[vaultsCount + index++] = "A backup was launched. Do not immediatly close the program. After a few seconds, you can safely ignore this message.";
|
|
||||||
};
|
|
||||||
|
|
||||||
*backupMessage = 0; // we reset it to show the message only once
|
// 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[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);
|
||||||
|
|
||||||
@@ -612,8 +594,7 @@ backup_config_end:
|
|||||||
}
|
}
|
||||||
|
|
||||||
debug("Selected vault: %s", vaultSelected);
|
debug("Selected vault: %s", vaultSelected);
|
||||||
if (strcmp(vaultSelected, "Create a new vault") != 0 && strcmp(vaultSelected, "Settings") != 0 && strcmp(vaultSelected, "Quit (Ctrl+C)") != 0 && strcmp(vaultSelected, "Backup now") != 0 &&
|
if (strcmp(vaultSelected, "Create a new vault") != 0 && strcmp(vaultSelected, "Settings") != 0 && strcmp(vaultSelected, "Quit (Ctrl+C)") != 0) {
|
||||||
strcmp(vaultSelected, "A backup was launched. Do not immediatly close the program. After a few seconds, you can safely ignore this message.") != 0) {
|
|
||||||
note_selection:
|
note_selection:
|
||||||
bypassSelectionVault = 0; // we must reset bypassSelectionVault to not get stuck in a
|
bypassSelectionVault = 0; // we must reset bypassSelectionVault to not get stuck in a
|
||||||
// infinite loop of bypassing
|
// infinite loop of bypassing
|
||||||
@@ -644,13 +625,12 @@ backup_config_end:
|
|||||||
altDebug("└------------------------------\n");
|
altDebug("└------------------------------\n");
|
||||||
}
|
}
|
||||||
// adds options
|
// adds options
|
||||||
int extraNotesOptions = 5;
|
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] = "Create new note";
|
||||||
filesArray[filesCount + 1] = "Search inside the vault";
|
filesArray[filesCount + 1] = "Back to vault selection";
|
||||||
filesArray[filesCount + 2] = "Back to vault selection";
|
filesArray[filesCount + 2] = "Delete vault";
|
||||||
filesArray[filesCount + 3] = "Delete vault";
|
filesArray[filesCount + 3] = "Quit (Ctrl+C)";
|
||||||
filesArray[filesCount + 4] = "Quit (Ctrl+C)";
|
|
||||||
char *noteSelected;
|
char *noteSelected;
|
||||||
// if we set to bypass the note selector
|
// if we set to bypass the note selector
|
||||||
if (bypassSelectionNote) {
|
if (bypassSelectionNote) {
|
||||||
@@ -681,7 +661,7 @@ backup_config_end:
|
|||||||
free(filesArray);
|
free(filesArray);
|
||||||
debug("Selected note: %s", 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 &&
|
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 && strcmp(noteSelected, "Search inside the vault") != 0) {
|
strcmp(noteSelected, "Quit (Ctrl+C)") != 0) {
|
||||||
open_note:
|
open_note:
|
||||||
bypassSelectionNote = 0; // we must reset bypassSelectionNote to avoid getting into an infinite
|
bypassSelectionNote = 0; // we must reset bypassSelectionNote to avoid getting into an infinite
|
||||||
// loop of bypassing the note selection
|
// loop of bypassing the note selection
|
||||||
@@ -718,13 +698,6 @@ backup_config_end:
|
|||||||
noteSelected = createNewNote(notesDirectoryString, vaultSelected, bypassSelectionNote, bypassSelectionNoteValue, journalRegex, shouldDebug);
|
noteSelected = createNewNote(notesDirectoryString, vaultSelected, bypassSelectionNote, bypassSelectionNoteValue, journalRegex, shouldDebug);
|
||||||
// we can just go back to open_note
|
// we can just go back to open_note
|
||||||
goto open_note;
|
goto open_note;
|
||||||
} else if (strcmp(noteSelected, "Search inside the vault") == 0) {
|
|
||||||
char *vaultPath = malloc(PATH_MAX);
|
|
||||||
snprintf(vaultPath, PATH_MAX, "%s/%s/", notesDirectoryString, vaultSelected);
|
|
||||||
char *result = fzfSelect(vaultPath, "Input text to be searched", shouldDebug);
|
|
||||||
bypassSelectionNote = 1;
|
|
||||||
bypassSelectionNoteValue = result;
|
|
||||||
free(vaultPath);
|
|
||||||
} 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) {
|
||||||
@@ -758,11 +731,6 @@ backup_config_end:
|
|||||||
} else if (strcmp(vaultSelected, "Settings") == 0) {
|
} else if (strcmp(vaultSelected, "Settings") == 0) {
|
||||||
openEditor(configPath, editorToOpen, 0, 0,
|
openEditor(configPath, editorToOpen, 0, 0,
|
||||||
shouldDebug); // as this is not a md file we set render and jumptoEnfOfFile to 0
|
shouldDebug); // as this is not a md file we set render and jumptoEnfOfFile to 0
|
||||||
} else if (strcmp(vaultSelected, "Backup now") == 0) {
|
|
||||||
debug("Running a forced backup");
|
|
||||||
forceBackup = 1;
|
|
||||||
handleBackups(directoriesArray, numDirectories, backupDirectoriesArray, homedir, interval, (const char **)rsyncArgs, rsyncArgsNumber, forceBackup, backupMessage, shouldDebug);
|
|
||||||
debug("backupMessage was set to %d by a normal backup", *backupMessage);
|
|
||||||
} else if (strcmp(vaultSelected, "Quit (Ctrl+C)") == 0) {
|
} else if (strcmp(vaultSelected, "Quit (Ctrl+C)") == 0) {
|
||||||
debug("The program was exited");
|
debug("The program was exited");
|
||||||
shouldExit = 1;
|
shouldExit = 1;
|
||||||
|
|||||||
@@ -179,7 +179,13 @@ char *fzfSelect(char *pathToFiles, char *selectText, int shouldDebug) {
|
|||||||
error(fd == -1, "program", "mkstemp failed");
|
error(fd == -1, "program", "mkstemp failed");
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* STEP 1:
|
||||||
|
* 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);
|
debug("INDEX CMD: %s", command);
|
||||||
|
|
||||||
if (system(command) != 0) {
|
if (system(command) != 0) {
|
||||||
@@ -187,6 +193,45 @@ char *fzfSelect(char *pathToFiles, char *selectText, int shouldDebug) {
|
|||||||
error(1, "program", "rg indexing failed");
|
error(1, "program", "rg indexing failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* STEP 2:
|
||||||
|
* Use fzf on the index file (NO rg anymore)
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
EXPLANATION:
|
||||||
|
|
||||||
|
cat %s
|
||||||
|
→ feeds prebuilt index file (format: file:line:content) into fzf
|
||||||
|
|
||||||
|
fzf --delimiter ':'
|
||||||
|
→ splits each line into fields:
|
||||||
|
{1} = file path
|
||||||
|
{2} = line number
|
||||||
|
{3} = content
|
||||||
|
|
||||||
|
--prompt
|
||||||
|
→ UI prompt text shown in fzf
|
||||||
|
|
||||||
|
--preview
|
||||||
|
→ runs a shell command for selected item:
|
||||||
|
file={1} → current file
|
||||||
|
line={2} → line number of match
|
||||||
|
|
||||||
|
nl -ba "$file"
|
||||||
|
→ prints file with line numbers
|
||||||
|
|
||||||
|
sed -n "$((line-5)),$((line+5))p"
|
||||||
|
→ extracts a window of 5 lines above and below match
|
||||||
|
|
||||||
|
sed "... -> ..."
|
||||||
|
→ highlights the matched line (middle of window) with red arrow
|
||||||
|
|
||||||
|
--preview-window=right:60%:hidden
|
||||||
|
→ preview appears on right, 60% width, initially hidden
|
||||||
|
|
||||||
|
--bind 'change:show-preview'
|
||||||
|
→ preview only appears after first selection change (not at startup)
|
||||||
|
*/
|
||||||
snprintf(command, sizeof(command),
|
snprintf(command, sizeof(command),
|
||||||
"cat %s | fzf --delimiter ':' --prompt='%s' "
|
"cat %s | fzf --delimiter ':' --prompt='%s' "
|
||||||
"--preview 'file={1}; line={2}; nl -ba \"$file\" | sed -n \"$((line-5)),$((line+5))p\" | "
|
"--preview 'file={1}; line={2}; nl -ba \"$file\" | sed -n \"$((line-5)),$((line+5))p\" | "
|
||||||
@@ -209,25 +254,16 @@ char *fzfSelect(char *pathToFiles, char *selectText, int shouldDebug) {
|
|||||||
buffer[strcspn(buffer, "\n")] = '\0';
|
buffer[strcspn(buffer, "\n")] = '\0';
|
||||||
result = strdup(buffer);
|
result = strdup(buffer);
|
||||||
}
|
}
|
||||||
debug("Buffer: %s", buffer);
|
|
||||||
debug("result: %s", result);
|
|
||||||
|
|
||||||
// cut at first ':'
|
// cut at first ':'
|
||||||
result = strtok(result, ":");
|
result = strtok(result, ":");
|
||||||
// we need to cut out the whole pathToFiles
|
// cut at / (because we need the full paths before and we only need to return the journal entry)
|
||||||
int pathToFilesLen = strlen(pathToFiles);
|
char *token = strtok(result, "/");
|
||||||
int cutOut = 0;
|
result = NULL;
|
||||||
for (int i = 0; i < pathToFilesLen; i++) {
|
while (token != NULL) {
|
||||||
if (pathToFiles[i] == result[i]) {
|
result = token;
|
||||||
cutOut = i;
|
token = strtok(NULL, "/"); // Passing NULL means “don’t start a new string, resume
|
||||||
}
|
}
|
||||||
}
|
|
||||||
result += cutOut + 1; // the + 1 cuts the first /
|
|
||||||
|
|
||||||
// in case we select a journal, we won't open the entry just yet. We only need to return the journal name (everything before [now the first] /
|
|
||||||
result = strtok(result, "/");
|
|
||||||
|
|
||||||
debug("Cleaned note: %s", result);
|
|
||||||
|
|
||||||
// clean up
|
// clean up
|
||||||
pclose(fzfPipe);
|
pclose(fzfPipe);
|
||||||
|
|||||||
+2
-8
@@ -167,9 +167,8 @@ void initAppFilesAndDirs(const char *home, const int shouldDebug) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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 forceBackup, int *backupMessage, const int shouldDebug) {
|
const int shouldDebug) {
|
||||||
int shouldBackup = 0;
|
int shouldBackup = 0;
|
||||||
|
|
||||||
time_t now = time(NULL);
|
time_t now = time(NULL);
|
||||||
debug("Time since epoch is %ld", (long)now);
|
debug("Time since epoch is %ld", (long)now);
|
||||||
char cacheFilePATH[PATH_MAX];
|
char cacheFilePATH[PATH_MAX];
|
||||||
@@ -204,12 +203,8 @@ void handleBackups(char **sourceDirectoryArray, const int sourceNumber, char **d
|
|||||||
error(1, "program", "Invalid timestamp in cache file: %s", line);
|
error(1, "program", "Invalid timestamp in cache file: %s", line);
|
||||||
}
|
}
|
||||||
double deltaTime = difftime(now, lastBackupTime);
|
double deltaTime = difftime(now, lastBackupTime);
|
||||||
if (deltaTime > interval || forceBackup) {
|
if (deltaTime > interval) {
|
||||||
if (!forceBackup) {
|
|
||||||
debug("(difftime) %f is greater than (interval) %d -> backuping...", deltaTime, interval);
|
debug("(difftime) %f is greater than (interval) %d -> backuping...", deltaTime, interval);
|
||||||
} else {
|
|
||||||
debug("Backup was forced. backuping...");
|
|
||||||
}
|
|
||||||
shouldBackup = 1;
|
shouldBackup = 1;
|
||||||
cacheFile = fopen(cacheFilePATH, "w");
|
cacheFile = fopen(cacheFilePATH, "w");
|
||||||
if (!cacheFile) {
|
if (!cacheFile) {
|
||||||
@@ -223,7 +218,6 @@ void handleBackups(char **sourceDirectoryArray, const int sourceNumber, char **d
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (shouldBackup) {
|
if (shouldBackup) {
|
||||||
*backupMessage = 1;
|
|
||||||
debug("A backup is needed");
|
debug("A backup is needed");
|
||||||
for (int i = 0; i < sourceNumber; i++) {
|
for (int i = 0; i < sourceNumber; i++) {
|
||||||
debug("%s", destinationDirectoryArray[i]);
|
debug("%s", destinationDirectoryArray[i]);
|
||||||
|
|||||||
+2
-3
@@ -81,8 +81,7 @@ If need launches in the background rsync to do the backuping.
|
|||||||
Each pair of source/destination will launch one rsync process.
|
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.
|
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
|
rsyncArgs is the array of arguments to be passed to rsync. Do not inclue destination or source. It
|
||||||
will be added in the function.
|
will be added in the function.*/
|
||||||
backupMessage will be set to 1 if a backup was launched.*/
|
|
||||||
void handleBackups(char **sourceDirectoryArray, const int sourceDirectoryNumber, char **destinationDirectoryArray, const char *homeDir, const int interval, const char **rsyncArgs, const int rsyncArgsNumber,
|
void handleBackups(char **sourceDirectoryArray, const int sourceDirectoryNumber, char **destinationDirectoryArray, const char *homeDir, const int interval, const char **rsyncArgs, const int rsyncArgsNumber,
|
||||||
const int forceBackup, int *backupMessage, const int shouldDebug);
|
const int shouldDebug);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user