Skip to content

Instantly share code, notes, and snippets.

@J053Fabi0
Last active March 9, 2024 05:29
Show Gist options
  • Save J053Fabi0/84245bf1932ce8e7a8690f21b534681c to your computer and use it in GitHub Desktop.
Save J053Fabi0/84245bf1932ce8e7a8690f21b534681c to your computer and use it in GitHub Desktop.
grimshot-extended
// To compile run:
// deno compile --allow-run --allow-read --allow-env screenshot.ts
// Add this to your sway config: for_window [class="fullscreen"] floating enable, fullscreen enable
// It requires viewnior to be installed. pacman -S viewnior
// By default it will save the screenshot in the Downloads folder, but you can specify a different folder with the -d flag.
// screenshot - Open the gui to take a screenshot and copy to clipboard
// screenshot full - Take a full screenshot and copy to clipboard
// screenshot -d /path/to/folder - Open the gui to take a screenshot and copy to clipboard to the specified folder
// screenshot -o - It compresses the screenshot with optipng before copying it to the clipboard. This requires optipng and dunst to be installed. pacman -S optipng dunst
import { join } from "https://deno.land/std@0.219.0/path/mod.ts";
import { parseArgs } from "https://deno.land/std@0.219.0/cli/parse_args.ts";
const {
_: [full],
optipng: optipng,
d: downloadsFolder,
} = parseArgs(Deno.args, {
string: "d",
boolean: "optipng",
alias: { d: "downloads-folder", optipng: "o" },
default: { d: Deno.env.get("XDG_DOWNLOAD_DIR") || join(Deno.env.get("HOME")!, "Downloads") },
});
async function runCommand(command: string, ...args: string[]): Promise<string> {
const output = await new Deno.Command(command, { args }).output();
return new TextDecoder().decode(output.stdout);
}
async function copyImage(path: string): Promise<void> {
const commandProcess = new Deno.Command("wl-copy", { args: ["-t", "image/png"], stdin: "piped" });
const child = commandProcess.spawn();
const writer = child.stdin.getWriter();
await writer.write(await Deno.readFile(path));
writer.releaseLock();
await child.stdin.close();
await child.status;
}
const printStep = ((id = "") =>
async function printStep(step: number, goal: number, fullRoute: string, text: string): Promise<void> {
const params: string[] = [];
if (id) params.push("--replace", id);
else params.push("--printid");
params.push("--timeout", step === goal ? "1000" : "0");
params.push("--icon", fullRoute);
params.push("--hints", `int:value:${Math.floor((step / goal) * 100)}`);
if (step === goal) params.push("--urgency", "critical");
const newId = await runCommand("dunstify", ...params, text);
if (!id) id = newId.trim();
})();
{
const filename = `${(await runCommand("date")).replace(/ /g, "-").slice(0, -1)}.png`;
const fullRoute = join(downloadsFolder, filename);
if (full) {
await runCommand("grimshot", "save", "output", fullRoute);
} else {
const tempFilename = `temp-${filename}`;
const tempFullRoute = join(downloadsFolder, tempFilename);
await runCommand("grimshot", "save", "output", tempFullRoute);
const viewniorCommandProcess = new Deno.Command("viewnior", { args: ["--class=fullscreen", tempFullRoute] });
const viewniorChildProcess = viewniorCommandProcess.spawn();
await runCommand("grimshot", "save", "area", fullRoute);
await runCommand("rm", tempFullRoute);
viewniorChildProcess.kill();
}
if ((await runCommand("ls", downloadsFolder)).includes(filename)) {
if (optipng) {
await printStep(1, 3, fullRoute, "Compressing scheenshot");
await runCommand("optipng", "-strip", "all", "-o", "1", "-quiet", "-clobber", fullRoute);
await printStep(2, 3, fullRoute, "Copying to clipboard");
await copyImage(fullRoute);
await printStep(3, 3, fullRoute, "Done!");
} else await copyImage(fullRoute);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment