Skip to content

Instantly share code, notes, and snippets.

@szhu
Created April 13, 2024 22:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save szhu/6fa1b56f7086df6677586d7aa7fe4f77 to your computer and use it in GitHub Desktop.
Save szhu/6fa1b56f7086df6677586d7aa7fe4f77 to your computer and use it in GitHub Desktop.
#!/opt/homebrew/bin/bun run
// <xbar.title>CPU Usage, Kill process</xbar.title>
// <xbar.version>v1.0</xbar.version>
// <xbar.author>Sean Zhu</xbar.author>
// <xbar.author.github>szhu</xbar.author.github>
// <xbar.desc>Shows the top 5 highest-CPU processes. Select a process to kill it.</xbar.desc>
// <xbar.image>https://raw.githubusercontent.com/Aleksandern/devman/master/images/BitBarCpuUsageKill.png</xbar.image>
// <xbar.dependencies>deno</xbar.dependencies>
// Based on: https://xbarapp.com/docs/plugins/System/cpu-usage-kill.5s.sh.html
import { $ } from "bun";
const XLineOptionFormatters = {
key: (value: string) => value,
href: (value: string) => value,
color: (value: string) => value,
font: (value: string) => value,
size: (value: number) => String(value),
shell: (args: string[]) =>
args.map((arg, i) => [i ? `param${i}` : "shell", JSON.stringify(arg)]),
terminal: (value: boolean) => String(value),
refresh: (value: boolean) => String(value),
dropdown: (value: boolean) => String(value),
length: (value: number) => String(value),
trim: (value: boolean) => String(value),
alternate: (value: boolean) => String(value),
templateImage: (value: string) => value,
image: (value: string) => value,
emojize: (value: boolean) => String(value),
ansi: (value: boolean) => String(value),
disabled: (value: boolean) => String(value),
};
const XlineOptionNames = //
Object.keys(XLineOptionFormatters) as (keyof typeof XLineOptionFormatters)[];
type XLineOptions = {
[name in keyof typeof XLineOptionFormatters]?: Parameters<
(typeof XLineOptionFormatters)[name]
>[0];
};
function formatLine(text: string, options: XLineOptions = {}) {
const parts = [text];
for (const name of XlineOptionNames) {
const optionValue = options[name];
if (options[name] != null) {
let formattedValue = XLineOptionFormatters[name](optionValue as never);
if (typeof formattedValue === "string") {
formattedValue = [[name, formattedValue]];
}
for (const [name, value] of formattedValue) {
parts.push(`${name}=${value}`);
}
}
}
return parts.join(" | ");
}
function o(text: string, options: XLineOptions = {}) {
console.log(formatLine(text, options));
}
// ---
const Bar = { size: 12 };
const Item = { size: 12 };
const ItemMono = { font: "Menlo", size: 10 };
const psOut = await $`ps acrx -o "pcpu pid command" | head -n 6`
.nothrow()
.text();
const [header, ...lines] = psOut.split("\n");
const parsedLines = lines.map((line) => {
const [cpu, pid] = line.trim().split(/ +/g);
return { text: line, cpu, pid };
});
o(`${parsedLines[0].cpu}%`, { ...Bar });
o("---");
o(header, { ...ItemMono, trim: false });
for (const line of parsedLines) {
if (!line.text) continue;
o(line.text, {
...ItemMono,
trim: false,
refresh: true,
shell: ["kill", "-9", line.pid],
});
}
o("Select a process above to kill it.", { ...ItemMono });
// o("---");
o("Open Activity Monitor", {
...Item,
key: "o",
shell: ["open", "-b", "com.apple.ActivityMonitor"],
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment