1
Fork 0

Begin the bulk script.

This commit is contained in:
Bauke 2023-02-25 17:37:04 +01:00
parent 9761204fda
commit f350e75ff5
Signed by: Bauke
GPG Key ID: C1C0F29952BCF558
4 changed files with 170 additions and 0 deletions

View File

@ -2,6 +2,7 @@
## Scripts
- [`bulk`]: bulk doer of things.
- [`codium-extensions`]: save and install VS Codium extensions using their identifier.
- [`copy-nixos-config`]: copies NixOS configuration from `$BAUKE_DIR/nix/<hostname>/` to `/etc/nixos/`.
- [`desktop-wallpaper`]: desktop wallpaper changer.
@ -11,6 +12,7 @@
- [`simple-git-push`]: `git push` with extra semantics.
- [`tauon-controls`]: remote control CLI for Tauon Music Box.
[`bulk`]: ./scripts/bulk/bulk.ts
[`codium-extensions`]: ./scripts/codium-extensions.ts
[`copy-nixos-config`]: ./scripts/copy-nixos-config.ts
[`desktop-wallpaper`]: ./scripts/desktop-wallpaper.ts

7
.bauke/bin/bulk Executable file
View File

@ -0,0 +1,7 @@
#!/usr/bin/env zsh
deno run \
--allow-read \
--allow-run \
"$BAUKE_DIR/scripts/bulk/bulk.ts" \
"$@"

View File

@ -0,0 +1,15 @@
import { Command } from "https://deno.land/x/cliffy@v0.25.5/command/mod.ts";
import { runCommand } from "./run.ts";
async function main(): Promise<void> {
await new Command()
.name("bulk")
.description("Bulk doer of things.")
.command("run", runCommand)
.parse(Deno.args);
}
if (import.meta.main) {
void main();
}

146
.bauke/scripts/bulk/run.ts Normal file
View File

@ -0,0 +1,146 @@
import { Command } from "https://deno.land/x/cliffy@v0.25.5/command/mod.ts";
import * as prompt from "https://deno.land/x/cliffy@v0.25.5/prompt/mod.ts";
export const runCommand = new Command()
.name("run")
.description("Run a command over a group of files and directories.")
.option(
"-d, --directory <directory:string>",
"Directories to include files from.",
{
collect: true,
required: true,
},
)
.option(
"--include-directories",
"Include directories found inside the directories.",
)
.action(async ({ directory, includeDirectories }) => {
await actionHandler({
directories: directory,
includeDirectories: includeDirectories ?? false,
});
});
async function actionHandler(
options: {
directories: string[];
includeDirectories: boolean;
},
): Promise<void> {
let command: string[] = [];
const previousPromptArgs: Map<number, string> = new Map();
const suggestedPromptArgs: Set<string> = new Set();
const substituteMarkers = {
absoluteFile: "$absoluteFile",
filename: "$filename",
};
for (const directory of options.directories) {
console.log(`\n## Input for ${directory}`);
const constructedCommands: string[][] = [];
const prompts = await prompt.prompt([
{
type: prompt.List,
name: "command",
message: "Arguments of the command to run separated by comma",
default: command,
suggestions: Object.values(substituteMarkers),
},
{
type: prompt.Confirm,
name: "confirmCommands",
message: "Manually approve each command invocation",
default: true,
},
]);
command = prompts.command ?? command;
for await (const file of Deno.readDir(directory)) {
if (!options.includeDirectories && file.isDirectory) {
continue;
}
const absoluteFile = await Deno.realPath(`${directory}/${file.name}`);
const constructedCommand: string[] = [];
let promptArgCount = 1;
const substitutes = [
[substituteMarkers.absoluteFile, absoluteFile],
[substituteMarkers.filename, file.name],
];
argumentLoop:
for (const argument of command) {
if (argument === "$prompt") {
const { promptedArg } = await prompt.prompt([{
type: prompt.Input,
name: "promptedArg",
message: `$prompt ${promptArgCount} for ${absoluteFile}`,
default: previousPromptArgs.get(promptArgCount) ?? "",
suggestions: Array.from(suggestedPromptArgs),
}]);
previousPromptArgs.set(promptArgCount, promptedArg!);
suggestedPromptArgs.add(promptedArg!);
constructedCommand.push(promptedArg!);
promptArgCount += 1;
} else {
for (const [marker, substitute] of substitutes) {
if (argument === marker) {
constructedCommand.push(substitute);
continue argumentLoop;
}
}
constructedCommand.push(argument);
}
}
if (prompts.confirmCommands) {
const { confirmedRun } = await prompt.prompt([
{
type: prompt.Confirm,
name: "confirmedRun",
message: `Run "${constructedCommand.join(" ")}"`,
default: true,
},
]);
if (!confirmedRun) {
continue;
}
}
constructedCommands.push(constructedCommand);
}
if (constructedCommands.length === 0) {
console.log("\n No commands to run.");
continue;
}
console.log("\n## Commands");
console.log(constructedCommands.map((c) => c.join(" ")).join("\n"));
const { confirmedRun } = await prompt.prompt([
{
type: prompt.Confirm,
name: "confirmedRun",
message: "Is this correct",
default: true,
},
]);
if (!confirmedRun) {
continue;
}
console.log("\n## Output");
for (const constructedCommand of constructedCommands) {
await Deno.run({
cmd: constructedCommand,
}).status();
}
}
}