From bfeafab6244e82add2799595dfb45178628ce1e8 Mon Sep 17 00:00:00 2001 From: Ardis Lu Date: Sat, 20 Apr 2024 21:51:45 -0700 Subject: [PATCH 1/1] Initial commit --- .gitignore | 1 + README.md | 45 ++++++++++++++++++++++++++++++++++++++ bun.lockb | Bin 0 -> 7024 bytes index.ts | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 13 +++++++++++ 5 files changed, 119 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 bun.lockb create mode 100644 index.ts create mode 100644 package.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/README.md b/README.md new file mode 100644 index 0000000..30a919b --- /dev/null +++ b/README.md @@ -0,0 +1,45 @@ +# Transcriber + +Transcriber is a [Bun](https://bun.sh/) CLI for executing combinations of shell +commands. + +## Example + +Given the following `input.json`: + +```json +{ + "command": "echo $arg1 $arg2 $arg3", + "args": { + "arg1": ["value1", "value2"], + "arg2": ["value3", "value4"], + "arg3": ["value5", "value6"] + } +} +``` + +Do: + +```plaintext +bun run index.ts -- --input input.json +$ echo value1 value3 value5 +value1 value3 value5 +$ echo value1 value3 value6 +value1 value3 value6 +$ echo value1 value4 value5 +value1 value4 value5 +$ echo value1 value4 value6 +value1 value4 value6 +$ echo value2 value3 value5 +value2 value3 value5 +$ echo value2 value3 value6 +value2 value3 value6 +$ echo value2 value4 value5 +value2 value4 value5 +$ echo value2 value4 value6 +value2 value4 value6 +``` + +The commands are run using [Bun Shell](https://bun.sh/docs/runtime/shell), which +implements its own set of +[built-in commands](https://bun.sh/docs/runtime/shell#builtin-commands). diff --git a/bun.lockb b/bun.lockb new file mode 100644 index 0000000000000000000000000000000000000000..02e9d799c920f54f34ccb35fc0c3f628dbded903 GIT binary patch literal 7024 zcmeHLdpuNm8$U84VdT<%7hQCn88a>^lx}D#L<()M!C+j5X2!il< zI*ecepW)8sF*v*sZTDcFA{;dTKo37Ju0Mz7703@@3uz&Gih~G(SR3VQbN78k_S2xD zgad1(Y-!8Y2ankEZ8dLPjvJTnB=~hSOad7uR)oSwI+{FRj3- zrp$Xw_TyGfedPiNtAOd#6b^Uj*2#~$V>#5dJosRsMVeM!?2d{j+Rj%8PdRU`7xOx@ z$-5#!?b)~k*LH{R_x*{R!f;8_%{QAlB+&HoQ~R{y>!;V;3MkeZ0hc!*L3arW9S#$? zF1W^i3C0Tn1su^R9&|vu`Xm_d37}O2z+VKs%>eK!5QxhF@IHXI8UX$z;Oz#0Cu9j? zu;6A50KXCN27pHuNDdCD1$`3izlih? zH3iiRREzo~7~cW-x!@o9Mnw_nz6i$80f0T=@%}}7u&)BH33MPq8sz}<3`Ci%~RITxBE?leUGXWS9%urVlcG6Y3o zI|PZ>0g9J0=>oOYES>dXUn;$b*i*K}O?%N|r=lgQX0G+_jrn`I&U75Er*ToBvMk`7c==uXW*m+xqJ9J5xrgC@iA6=LJ+vUsFndq$;d)%`vG~k34DBmY?Xu z_L(eqZS_%)5D_m$v=`*1c@qlez0NkXZC7->_j=j34ZEk9eLpq%S~7oe(v_RR&)H+E z!UcuvP8;2umc!h=*J0tsTJz)~8!S2#L*H{{vYaN$lkws`jHxM(TR9Vc93-4SKp@ddxBzvE+nGot=?4X=LSmkXUYaC)Xap`l*El1b>)2wJk%}JN)1yqwC zCe;O343>Ma&3>|m(Bs(G#yPUKh6^`cAoGCYm9Dpx4^79kw6)SLUD|&uqpcJc@9OmQ zcYTt#?oytydiw=Iitd?a@2uLn)6J4!9(msS_|@;qOkan}7UqkB8eR6x=5!ISc)y`q zjD=$Eo_A%*`1twX-B$VGs(RhL+5=w^>l+L<`Gs;<#OQq8`ONIi`|`r-L50R0^%|b) z>U`s@+{3q42`WvV`+Q##c~6QL*G0rl8Lci$&1=m4Nnrll_L-Mt>)!aswcfcjay_NPjDPB}Bu~14p)$Gfv zcBW3frRCdP*I2cz=}Aq(p+`Xl{AyOGwNvVN1!~8cH}(f+F3VV+rIV0b=9;dcwjpkv zSxF>ij5|@|7ecp{;ze~G3q{v1(d2Q4aGqk0{pxL*T29d# zPCok2e>5qdQ_~tEJUZh@u1`>sucr|QrFhX^ z#zL9(PAQ|HHSFpZ#oBLqb(#BHHlj`+NraaT`8Q_GQMG4E(=mU@Q3+e2~EFaUg%lFXBYp$OrO;d?Mc{1{@Fag?-}hh$7NoBKqJ0Q8aaB8GRdU40$q= zTqm=8o>1Qg_e~UJRxw$0JvtM0b5In~xbvbQ!=y9mdN7K6OSrc)NMwPpL`nAvcYnZw z$N-cHR@6_z{Tzw}gF8;R~Vd z52y2j0(=GZK)yFaGKWFy`cD&Qh%WSwK%H8kqI1GHpJ0I*fQMfiTKonGXdW2C5kYC5 zY}g`p?f!>}(!#!svhw0Fe>;(aXoFUpCC zf-EY$Ku-?&H&pNmHpv_a1-6>Fe4|i4k3lW~g%pi^Ac!Ie=6P~GxSzca>1jYCeM%EO d5ez>UhNL3)sI0)(t", + "JSON file with command and arguments to execute", + ); +program.parse(); +const options = program.opts(); + +const file = Bun.file(options.input); +const json = await file.json(); +const { command, args } = json; + +// Based on: https://stackoverflow.com/a/32839413/21084807 +function getCombinations( + args, + index = 0, + results: Array> = [], + current = {}, +): Array> { + const allKeys = Object.keys(args); + const key = allKeys[index]; + const values = args[key]; + + for (let i = 0; i < values.length; i++) { + current[key] = values[i]; + + if (index + 1 < allKeys.length) { + getCombinations(args, index + 1, results, current); + } else { + results.push(structuredClone(current)); + } + } + + return results; +} + +const c = Object.defineProperty([command], "raw", { + value: [command], +}) as unknown as TemplateStringsArray; + +if (args === undefined) { + console.log(`$ ${command}`); + await $(c); +} else { + const runs = getCombinations(args); + for (const options of runs) { + let input = command; + for (const [key, value] of Object.entries(options)) { + input = input.replaceAll(`$${key}`, value); + } + console.log(`$ ${input}`); + await $(c).env(options); + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..3d6c71a --- /dev/null +++ b/package.json @@ -0,0 +1,13 @@ +{ + "name": "transcriber", + "type": "module", + "module": "index.ts", + "dependencies": { + "@commander-js/extra-typings": "^12.0.1", + "bun": "1.1.4", + "commander": "12.0.0" + }, + "devDependencies": { + "@types/bun": "1.1.0" + } +} -- 2.47.3