From d494159a58299f8c54b377a3d6eec997af53b3b2 Mon Sep 17 00:00:00 2001 From: Tomas Rivera <137088692+Totorile1@users.noreply.github.com> Date: Sun, 29 Mar 2026 17:52:40 +0200 Subject: [PATCH] coded the vault and note selector --- a.out | Bin 16664 -> 21936 bytes shell.nix | 1 + startup.c | 195 ++++++++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 174 insertions(+), 22 deletions(-) diff --git a/a.out b/a.out index dd386a02cd2224ce6f4de4221659b75d188a2d38..f03877136f5bba6d0558c5e6881bc5e0f0d26732 100755 GIT binary patch literal 21936 zcmeHPeRNw#l^@&raFZr-ztaNkYubc_)QaWUjvbn<6@TO@*oldq^nEGg2H z?F2|uT$c)05a5)AcQNVJqJZBx^2tNq=1 zbLD465BBuzU%MLn>CXMly?18r%)B>m-kWzyGU<` z(%Yf*m^LVXGG%{K8D%-wnE8kj+OA-xrF!j3zLaW8k16}U|2ZS@cJk{}dU2O&xRk2u z3Z|Uj`=LjE`JV>W>|(3R&#oN~EB`a4enMe&G(5gKX~Yu2)uV~Efn@9G*kGhFw0CVh z(b(t;H1BB$wMN@~&0_&y{ZJ%4=&x^dHZ{~Yx>{F*TOA41N5aw6c>Q>5OMOd|GZ}L> zO1m_yZon}g$JG)MVx^*&D@ug=>UB7-Cq{(}Kv&>cj)RK57{_~XSi?17uCM^qUEYm@ z@})L^7mj!0xERN^I4E3dlDGZKZDci|hM~AnftP_U!a?nFrNSJbt8gs9LBsDII4;4V z;ov~+u@uKuIF=~T+7GCHWP{{P{B9{l7=<4Pe>7so%KwI;NWLfy-2lqrUK{+N4Nm^n zaFm8;0F<-;Wt;NMv%z1nvGW}p{Dcj@&c?oGg98>Cj?zGvl5+K;KChJugWqQ(|4F2k zvlFwCKWroaHQ?MA5iN#~AXd))&u#F}+2C7k@Gshwv(5(pf{mU3u)#lXW5;QOkJ;cK zv$21LjeI}wa{i3k*tyrn&I301avR)jga6Pb--R~vw*jZ~$$7!+8R+!}f{EZzIB5hE z1HB!QSTs1`8;k^n*E=*4i+YoWFJXASLW-6Z^l$3lvf10`OC*EBjCTejL4z4jvfoIA zqeCifW6;<#xHITCJVtOtgri|2=}!p%U?S+-CB}S)k?_W%Vr(dA_=iO>8W;;l#mHzJ z7K|~GGy)_&=8pt@2@#D2{lhV_E4U}_3$Sh|BoaX=1w=e$BvA`gz`x7uAKv8+`N9zZ z(pHEN5lRGuA~+s4VA)4Mi9jkY{E=8P7zigsC>9S!Va^wc#Qe~NxGx|TM;M~3pz_g( z4@E@@gNX!W{o_7wC>-@g!h3@vWCSA-G8B+zWd?$b6N@57tz{ZZgyB4t#Xk}kyOXhm zAwtPuaF?LGb|zy{y0E&4i~3V=dUA|_7MX0uHg{~>+TYdR;vMj8?%v{Ub~ZR&ZEbC? zhQ>8QrQO^D*yU_&Kv>(*DmM0bHgtF!oom+2M4O7ywZ+&Bw#GRVZ*(?WCl5p6L~?Jq zX*4uGKHB1H*cEa`o0GeDM+XDDLxE^`Z$0K2^~quQgys$FEYprq$hS7)TN4krxWa1( zL&?2s_N?6--x*IP#ztFq?b=;09Z>Ibu0@SXl>_m}cwo3C+0>TYJ=8olIOf_jf-1KL zMw5F3hL}v$<6FZOnJ9yxFze zRX^nS*SngWYn%<3BVno(9>id*7FGDG!BH*$<{&;-#t5OKMjmq&HRWn>&9BB>s=6pU z2k~mmbZW!}pfoS27LQ@f)4YSG?lrwP<9Dt&tuXzs>oIMp5wC!!Pz8%WQfb70Fs3#0#kGpRRPyu0D#aUDhB0lMBbpVTx{CN};Ra8E?+bW7 zzGJzG_o)dm_b06u+4Soag_9_gQe7<8!#h zg42BghaDE2?qfI%TX33lbBJ4TzTcv>aSKlOOdR%GaE(FG`z-ji7W{w(UuwZWYr(De za1UB=x+mjs(1NR>E|U&faJrAB8hYVNmI<2HRVYg89b=@Z9lk4jGzniEbT3d;=q zI<9F)jQC+n%bzJAEZa#uE!pHxNq&%cTB^xsC4U?7v_z9XB>Anx)6z`-LCJ3-o*sAR z4@iCk@w7yf-!J)f#M5#}J}&u2;%P}HzeDoxA)c0E@_mwDN<1yWqGpCBI+tM~J5-mV8|DUnicH zR`NR}{}tkCNhRMW`M)EcmQwQVlK&j>w1kpxko>2Jr=^p;Ci#yMPfI5GI>~>8cv>pS z3(4;#o|Z`RXWyjyCy3XGKO^~_#M6>U{*>egiKnHId{*+e5l>5i`9nqd&;jr=Y|}IA z+u&_I{ha$|_jdO-_dq}TV{1U4YFb7MgnBx4QqMGB0-4-u6bL=kanGmGzg*{zP%rbO zkLl?rau36HPx`mH+fC|8AJ6TEbZ;hA)sucL_Z;Bf^qHP?{s?u|p7c2=>FJ}nA3(^{ zcHA*}4ETlendhqzKtY~fL}hv+_Y+b~pP&I#M|=%LQMAc# zNU^znQmpHsKK0>)uBY@&DyyfrWpj%#5cJHVb11n!mC7EWehh674EzxW;Eaz#G551K z5TEMGlJ)DlT)zo99oO6gQ6b(pb>nY66UVA@-%ui+wquFk>6xbE)Fpe;h1^am`_#59 z%6c1Yz3kXGHwH&ieKT`60}1Jl=*f^H@?FP8bAGN*e6Kop1%?~M*CFvcMW24pmCfyw znV<&Qp7is2X4|9bu19l!qB{6fkD7(gELusGp*kGPIn6rEp*ma)-H8uBDvYIFu0qIC z{x>`mPgLbz{x1~M-}R`c?TN(idMD2r7o)-lJ#F2ZQA_^phk8%?54nG#BA_WcKwVi> z>|{V+b*bzcj>&&QopG*e{eb&+_Z{v#-QGKn;zYIt3)Dwwggs7e4WCwHxa(83xtpkX zu=N`9re=N?HV>1`3xDsK+NbH01;;%!XmX=6)2@U0_0pMhPhctS2#s;JcpN7bviN&d zx`$x#g@=*%=Sh-A8%yp~l1Cx=!l!aKg3PpL=m4F6UBCCFe|)E&{KEitB6ZPO>#e}$qL zt;U7=)cO-(aw}2JTmWS~G50a>Rd*ooV*aF`A44LSXR1Y?x+&iUf608d%^LW3zeo>R z^oa|v7y8{V(ldQM{fPDl8fkCp>DSRm2QE;36eox|>IBhs5?%Ete=_^as@KuRbdI== z2I3QwE1(TKbe=#zeBmlp4o~LJOQdeZBOQrEM$Arc~`do zTU1kd278=hJ(;;zplWokN>iShM;c_FujP(_z3o;ywR`|>oSM{uFB4~lSTEXfO`hxm zN+U|2dW=f4In(qe)fcC@oR=)6pViZ{jJXF9plKoy=N*z zUXX>Rs!)~D0jvXSxu_O$0=VlJ(&jk9k6E8-&~MQ58Tr9_qc&_(<5n9=AE+X z_4G5j08~*=YI>yP9zu1g=@Hk{omWoh=Rr01RiMT8$2EZ3|6H;C5wo^8hM;@Elm2PH z>z8Pn6}T=R&bBzJi- zJ;y~?W^;9C+smmRA`913kJCfe&U7y(1HC7uLZg}G$*B(?!*wHb*|(9WG>0s5L9$lV z%XOm)rt!oVE!`dEp?b8!(!})5#-_Vm6VnS)x95h)wEvf$sm`bA^0T7c$fseC_FrF( z?r1dLwQ*uPX{?%<9&=3QaZPb&IJ^^InXqE0iit5r? zP&hhH=f4K@!1@~4b4)%|V&ehuxYVn;d~xB=KH|_zn1g_d|11;^g4BWDj?;VHD}}-^;kZa;2?zZtXcm_pdO7A0 zuI)E~Qs8$rs`hRbRpWJ4@3?S&?E$0_PB-}vzFa6QC&AA7m}Q#plQ)5`K;C`S^o#4d z7cbf5SU6U@U)*%nd*8F>`lTdC`nTigJ6kAFSvimq14k>$NQ){IR^Ye~M-wo5?^U=L z*WFv)v1s1ypQ!oxoXp(&=S|G7eq;ek*1wQsAI5PQb$ZDvJ8Y3XOR@tCZ-Cqx93R5f z`5&yZ-KK2U{qs5}=GVNlip1Z)P`+1B@7Mk#rdO}Xi362m)1rC3Gq!75t4Z3;WuF84 z4LC445F0md6V>}gmN3eW0^UlKJm%&y;9ay?=_E@&A$iiLfcs79ED^dO2tuX$Ti+&?HZ2^Zgq z{=q7f=XZ(uJ$hPtr@(Voey5nkV37R0AgWE zhMZDdp!j`CpXZhQ?z8oscoJ1&;=pE8QB_myPzf~era%uoDe$}1_t6tc1jhH{5eo&b zN3HT7&r>;ne&?Cxuv_;WwMYk&& zQgl?&dlmhRqF++n5ni8M~;pOCM+?T^w0kt*yWuIn=qDmR54II6^Dg3k|xQTQkhvd`x=3F3#AsjF~z%;y`% zzm7<`@;@r&FA{Gwvg8acC;xq!Tqk&6JWD@~NELQK^Lc~umnD9MC>=N9Y9Tb*X|3wZ z@^2tw-4DX}VmPE6ew7VA0{a)kKm45txyArvD{bUGz%|ayLT|B=58L1$w88JU!5<>L zda>Z^1!qm`3FYehqz(R}4PLOpFOvS}+-7J!@QZ}QTyy};=g}LbKWF4PM%O`&84Dc( zURS1l4I4Z6+299(FSXd^=usQ_pWEQC0=MozVmtJGkBh3WERH+IuLoYv{~b2?c4ddp zQ*6g?BY(HV(LYtkla}><1wvq6n> zRJ7lpFkH?Uwl@0)!(PKTMEk1~Mk?;~3nUFr0Ibe{3X9yUGL3hVl}$+dAyUn!9h07pvuoJ=opt8wq*?sgaRAP_b}c z+IBum6otZOY$}r1+r8D@+vV-r+)2CMy_gkvyL1KWom+)>W6zci?jG-!?(Y7s0q=l& zLr)h3J8#|W?)7w-TfN(PJ2h>LK7W6FaZ5aJY;U*Om0hw2pLVp*GA;Lo&q8Q3`z*k^ z-@TYXd$*;()E;`f{LQWPoLY82xw#X*XqhT3x6RK&{_J-KJX^4VJ`j$2Q`mJcx8$F% zTlT{P=qNtJXYRh|-So3m`EvqXfznOyvv=vwQdN8PXJO`N2keZQ-zMPHvcB?q@r4D| zv(%RlSiZDq<~IyxWsmA6W8Pt3G=Q%&m>)>6)5g~mw##Q%-HF&pCqL4f{dETUWr0~4 zn4dqG1(_dUu*=5l9ZV*b|4To#P&Csd)V6!`S&{m%K{1&+jOEJ;MSQKmC`NaX-%2Q= zay-dzMR1wQI+{)vzC=)ccmm##PtM30(k;a=Jj}9de!5{6WDecgpRAbuxrU-R4XKd) zbVCuM!lED1$0KH8-XQf`)EZv_uzozED72<&=4%#Q&(aP;AFP;BSR>@uC*+Au2xoH7 zh~XOqH4-Kr<`_Ps5lqB|b10f}4*QbB!Wq~Tg}6x#JX)lb(O@DO#*;-W<3(B`81a#U zip3*_a8gGWPDGtUF+_~uIDY9|4565;s53aM&c4F|7-3F0=>eh4BA&p5)r7G}LGBHn zdb(&x+va)NG|6!?ONBuWvf#dvupbffsuNvOIMD&Fu(#zJe*QdTMp&2Zp|t+%fzlca=g;dZOm9(oTz-~gx(VsD zX2U$M+c14l>9dcy{0bJgB0{!Vf4^EsV#@1CoImSx{ryURgEGkLQcQUri}XpSRDT2* z`GnWega(F!CV%BOz|5HW%jIBf7!j+!rkN>BM`ips{{{|i0y%+U)-Kg(IvUYxXS&!+jAVV(V{P}w> zxBLZtvQ6P795i-VpVxi(dy)KINE-hXIA89EW5BHW^Lo+&S~x?9+q56sc?~jF{o?vk zJ8931Gn1RipZPZtAzNI2zE7)bHzhb9lQZ+;I8l0?lJZyGy_m%MrT2tf9V;#Ny`nbW zVQDv+R_dGxv>r*exIBFRqv6eEN3 Cv9mq^ literal 16664 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 ZN^aNI+V|!z6RG-Ir)_bB4Hb9${}XY+p*;Wq diff --git a/shell.nix b/shell.nix index 3b317dd..bb87a5d 100644 --- a/shell.nix +++ b/shell.nix @@ -4,6 +4,7 @@ pkgs.mkShell { buildInputs = [ pkgs.vivify pkgs.cjson + pkgs.ncurses pkgs.pkg-config ]; } diff --git a/startup.c b/startup.c index 45d39d2..2c5278d 100644 --- a/startup.c +++ b/startup.c @@ -1,8 +1,150 @@ +//gcc startup.c $(pkg-config --cflags --libs libcjson ncurses) #include #include #include #include #include +#include +#include // for PATH_MAX +#include + +char** getVaultsFromDirectory(char *dirString, size_t *count) { + // (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 + printf("Opening %s aka the directory of vaults\n", 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("Could not open current directory" ); + exit(1); //something is fucked up + } + 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() + while ((vaultsDirectoryEntry = readdir(vaultsDirectory)) != NULL) { + printf("%s\n", vaultsDirectoryEntry->d_name); // debugs every file/directory + 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 + + struct stat metadataPathEntry; + if (stat(fullPathEntry, &metadataPathEntry) == 0 && S_ISDIR(metadataPathEntry.st_mode)) { // if this entry is a directory + dirsArray = realloc(dirsArray, (dirsCount + 1)*sizeof(char*)); // resize dirsArray so that + dirsArray[dirsCount] = strdup(vaultsDirectoryEntry->d_name); // copy the dir name into dirsArray + dirsCount++; + } + } + } + // (TODO LATER) Alphabetically sort them + + // free's some used memory + closedir(vaultsDirectory); + *count = dirsCount; + return dirsArray; +} + +char** getNotesFromVault(char *pathToVault, char *vault, int *count) { + // this function is inputed a path to a vault (which was selected before) and outpus all the suitable notes (so not the hidden ones) + printf("Opening %s aka the vault\n", vault); + + // originally from https://www.geeksforgeeks.org/c/c-program-list-files-sub-directories-directory/ + struct dirent *notesDirectoryEntry; + 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("Could not open current directory" ); + exit(1); //something is fucked up + } + 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() + while ((notesDirectoryEntry = readdir(vaultDirectory)) != NULL) { + printf("%s\n", notesDirectoryEntry->d_name); // debugs every note + if (notesDirectoryEntry->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 + + struct stat metadataPathEntry; + if (stat(fullPathEntry, &metadataPathEntry) == 0 && !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 + notesCount++; + } + } + } + // (TODO LATER) Alphabetically sort them + // free's some used memory + closedir(vaultDirectory); + *count = notesCount; // passes the number of files + return notesArray; +} + +char* ncursesSelect(char **options, char *optionsType, size_t optionsNumber) { // this fonction make a TUI to select one of multiple options. + int highlight = 0; //curently highlighted option + int choice = 1; //selected index + int key; + + initscr(); //initialize ncurses + cbreak(); // disable line buffering + noecho(); // don't echo key presses + keypad(stdscr, TRUE); // enable arrow keys + while (1) { + clear(); + mvprintw(0,0, "Select %s (Use arrows or WASD, Enter to select):", optionsType); + + // 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]); + if (i == highlight) { + attroff(A_REVERSE); + } + } + key = getch(); //get some int which value correspond to some key being pressed + + switch(key) { + case KEY_UP: + case 'w': + case 'W': + highlight--; + if (highlight < 0) { + highlight = optionsNumber - 1;// can't select the -1nth option + } + break; + case 's': + case 'S': + case KEY_DOWN: + highlight++; + if (highlight >= optionsNumber) { + highlight = 0; + } + break; + case 10: //\n + choice = highlight; + goto end_loop; + } + } + end_loop: + endwin(); // end ncurses mode + return options[choice]; +} + +int compareString(const void *a, const void *b) { // this will be the function used by qsort + const char *str1 = *(const char **)a; + const char *str2 = *(const char **)b; + return strcmp(str1, str2); // strcmp returns <0, 0, >0 +} + int main() { // Read config file @@ -44,33 +186,42 @@ int main() { } else { notesDirectoryString = "~/Documents/Notes/"; // default } - - // (TODO LATER) it might be a good idea to check if these directories exist - // (TODO LATER) expand ~ as it does not work with opendir() - printf("Opening %s\n", notesDirectoryString); - - //--------------------------------------------------------------------------------------- - // https://www.geeksforgeeks.org/c/c-program-list-files-sub-directories-directory/ - struct dirent *notesDirectoryEntry; - DIR *notesDirectory = opendir(notesDirectoryString); - if (notesDirectory == NULL) // opendir returns NULL if couldn't open directory - { - printf("Could not open current directory" ); - return 1; + size_t vaultsCount = 0; + char **vaultsArray = getVaultsFromDirectory(notesDirectoryString, &vaultsCount); + qsort(vaultsArray, vaultsCount, sizeof(const char *), compareString); // sorts the vaults alphabetically + printf("Available vaults:\n"); + for (size_t i = 0; i < vaultsCount; i++) { + printf("%s\n", vaultsArray[i]); } - // Refer https://pubs.opengroup.org/onlinepubs/7990989775/xsh/readdir.html - // for readdir() - while ((notesDirectoryEntry = readdir(notesDirectory)) != NULL) - printf("%s\n", notesDirectoryEntry->d_name); + + // adds "create a new vault" into the vaultsArray + // (TODO LATER) maybe add an option for setting + const int extraOptions = 2; + vaultsArray = realloc(vaultsArray, (vaultsCount + extraOptions)*sizeof(char*)); // resize dirsArray so that + // (TODO LATER) add a way to Colorize the extraOptions + vaultsArray[vaultsCount] = "Create a new vault"; // some more options that are not vaults + vaultsArray[vaultsCount+1] = "Settings"; + // select a vault + char *vaultSelected = ncursesSelect(vaultsArray, "vault", vaultsCount + extraOptions); + printf("Selected vault:%s\n", vaultSelected); + + if (vaultSelected != "Create a new vault" || vaultSelected != "Settings") { + int filesCount = 0; + char **filesArray = getNotesFromVault(notesDirectoryString, vaultSelected, &filesCount); + qsort(filesArray, filesCount, sizeof(const char *), compareString); // sorts the notes alphabetically + // + printf("Available notes:\n"); + for (size_t i = 0; i < filesCount; i++) { + printf("%s\n", filesArray[i]); + } + } else if (vaultSelected == "Create a new vault") { - - //-------------------------------------------------------------------------------------- - - // list all the directories (except hidden ones). They are like obsidian vaults + } else if (vaultSelected == "Settings") { + //(TODO LATER) add a way to change the config.json from the app or at least show all the options + } // Cleanup if (dirJsonFormat && notesDirectoryString != dirJsonFormat->valuestring) free(notesDirectoryString); // only free strdup - closedir(notesDirectory); cJSON_Delete(json); free(data);