diff --git a/LICENSE b/LICENSE index f288702..53d1f3d 100644 --- a/LICENSE +++ b/LICENSE @@ -672,3 +672,4 @@ may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . + diff --git a/README.md b/README.md index 89e5666..71deb50 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ The goal was a terminal-based interface for accessing vaults and notes using sta ### How to install 1. Have installed `ncurses`, `cjson` and `pkg-config`. -2. Have a supported editor: `vim` and `neovim` (for the moment) +2. Have a supported editor: `vim`, `neovim` and `nano` (for the moment) 3. Clone the repository. ```shell git clone https://github.com/Totorile1/NoteWrapper.git @@ -23,6 +23,25 @@ make ### Usage If you want to render with Vivify with the flags `-r`, `--render` or with the option in the config file, you must have installed the plugins for your specific editor ([for Vim and Neovim](https://github.com/jannis-baum/vivify.vim)) + +### Editor support + +`NoteWrapper` relies on certain editor features, so not all of its functionality is supported by every editor. + +Here are the features that depend on editor support: + +- **Bufferless rendering**: As soon as you write something in the note (even without saving), it is rendered. +- **Cursor following**: The rendered view follows your cursor. For example, if you move to the bottom of a note, the rendered view will also scroll to the bottom. +- **Jump to end on open**: Automatically jumps to the end of the file when opening it. + +The first two features depend on [Vivify's plugin for editors](https://github.com/jannis-baum/Vivify?tab=readme-ov-file#existing-integration). + +| Editor | Bufferless | Cursor | Jump to end | +|---------|------------|--------|-------------| +| Neovim | ✅ | ✅ | ✅ | +| Vim | ✅ | ✅ | ✅ | +| Nano | ❌ | ❌ | ✅ | + ### Configuration Change `$/.config/notewrapper/config.json`. If it does not exist. On building, it should copy a default config. @@ -49,3 +68,4 @@ Change `$/.config/notewrapper/config.json`. If it does not exist. On building, i - [ ] Add a way to delete notes - [x] Comply with GPL-3 notice (add info about no waranty, etc.) - [ ] A converter for both type of journals + diff --git a/src/main.c b/src/main.c index c489b38..ae2afbb 100644 --- a/src/main.c +++ b/src/main.c @@ -193,7 +193,7 @@ int main(int argc, char *argv[]) { } else if (strcmp(argv[i], "--version") == 0) { printf("There is still no released version\n\n Copyright (C) 2026 Tomás Rivera\n License GPLv3: GNU GPL version 3 .\n This is free software: you are free to change and redistribute it.\n There is NO WARRANTY, to the extent permitted by law.\n\n Written by Tomás Rivera.\n"); return 0; - } else if (argv[i][0] == '-') { + } else if (argv[i][0] == '-' && strcmp(argv[i], "-V") != 0 && strcmp(argv[i], "--verbose") != 0 && strcmp(argv[i], "-c") != 0 && strcmp(argv[i], "--config")) { error(1, "user", "unexpected argument \"%s\" found\nFor more information, try \"--help\".", argv[i]); } } diff --git a/src/utils.c b/src/utils.c index b7d4d4c..855f0f6 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,7 +1,7 @@ #include "utils.h" -const char *supportedEditor[] = {"neovim", "vim"}; -const int numEditors = 2; +const char *supportedEditor[] = {"neovim", "vim", "nano"}; +const int numEditors = 3; int compareString(const void *a, const void *b) { const char *str1 = *(const char **)a; @@ -169,7 +169,7 @@ int rmrf(char *path) { } -int openEditor(char *path, char *editor, int render, int shouldJumpToEndOfFile, int shouldDebug) { +/*int openEditor(char *path, char *editor, int render, int shouldJumpToEndOfFile, int shouldDebug) { // (TODO LATER) Bug app breaks if browser was not already launched before vivify // (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 @@ -221,11 +221,121 @@ int openEditor(char *path, char *editor, int render, int shouldJumpToEndOfFile, error(1, "program", "execlp() failed."); } } + } else if (strcmp(editor, "nano") == 0) { + if (render) { // (TODO LATER) We should check if Vivify exist + if (shouldJumpToEndOfFile) { + debug("Running nano + %s && viv %s:99999", path, path); + execlp("nano", "nano", "+", path, NULL); + // we need to append :99999 to the path for vivify to go at the end + strncat(path, ":99999", PATH_MAX); + execlp("viv", "viv", path, NULL); + } else { + debug("Running nano %s && viv %s", path, path); + execlp("nano", "nano", path, NULL); + execlp("viv", "viv", path, NULL); + } + } else { + if (shouldJumpToEndOfFile) { + debug("Running nano + %s", path); + execlp("nano", "nano", "+", path, NULL); + error(1, "program", "execlp() failed."); + } else { + debug("Running nano %s", path); + execlp("nano", "nano", path, NULL); + } + } } } else { // Parent process: wait for child to finish int status; waitpid(pid, &status, 0); } // (TODO LATER) add a options to kill the browser when closing. This will solve the bug where -R does renders when the file was previously opened with -r. + return 0; +}*/ +int openEditor(char *path, char *editor, int render, int shouldJumpToEndOfFile, int shouldDebug) { + + pid_t editor_pid = fork(); + error(editor_pid < 0, "program", "fork() failed."); + + if (editor_pid == 0) { + // ========================= + // CHILD: launch editor + // ========================= + + // ---- NEOVIM / VIM ---- + if (strcmp(editor, "neovim") == 0 || strcmp(editor, "vim") == 0) { + const char *bin = (strcmp(editor, "neovim") == 0) ? "nvim" : "vim"; + + if (render) { + if (shouldJumpToEndOfFile) { + debug("Running %s +:$ +:Vivify %s", bin, path); + execlp(bin, bin, "+:$", "+:Vivify", path, NULL); + } else { + debug("Running %s +:Vivify %s", bin, path); + execlp(bin, bin, "+:Vivify", path, NULL); + } + } else { + if (shouldJumpToEndOfFile) { + debug("Running %s +:$ %s", bin, path); + execlp(bin, bin, "+:$", path, NULL); + } else { + debug("Running %s %s", bin, path); + execlp(bin, bin, path, NULL); + } + } + + error(1, "program", "execlp() failed."); + } + + // ---- NANO ---- + else if (strcmp(editor, "nano") == 0) { + + // If render enabled → spawn viv in parallel + if (render) { + pid_t viv_pid = fork(); + error(viv_pid < 0, "program", "fork() failed."); + + if (viv_pid == 0) { + // GRANDCHILD → viv + char viv_path[PATH_MAX]; + strncpy(viv_path, path, PATH_MAX - 1); + viv_path[PATH_MAX - 1] = '\0'; + + if (shouldJumpToEndOfFile) { + strncat(viv_path, ":99999", + PATH_MAX - strlen(viv_path) - 1); + } + + debug("Running viv %s", viv_path); + execlp("viv", "viv", viv_path, NULL); + error(1, "program", "execlp() failed."); + } + // IMPORTANT: do NOT wait for viv + } + + // Now run nano (this replaces the child process) + if (shouldJumpToEndOfFile) { + debug("Running nano + %s", path); + execlp("nano", "nano", "+", path, NULL); + } else { + debug("Running nano %s", path); + execlp("nano", "nano", path, NULL); + } + + error(1, "program", "execlp() failed."); + } + + // ---- UNKNOWN EDITOR ---- + else { + error(1, "program", "Unknown editor."); + } + } + + // ========================= + // PARENT: wait ONLY editor + // ========================= + int status; + waitpid(editor_pid, &status, 0); + return 0; }