#!/usr/bin/env python3
# cleat: {"name":"Kill Process","keyword":"kill","icon":"xmark.octagon","subtitle":"Force quit a process by name","version":"1.3.1","requires":["python3"],"examples":["kill "],"emptyMessage":"No matching processes. Try another name."}
import json, os, signal, subprocess, sys


def main():
    if len(sys.argv) > 1 and sys.argv[1] == '--run':
        pid = int(sys.argv[2])
        if pid <= 1:
            raise ValueError('Invalid process ID')
        os.kill(pid, signal.SIGKILL)
        return
    query = (sys.argv[1] if len(sys.argv) > 1 else '').casefold()
    result = subprocess.run(['ps', '-axo', 'pid=,pcpu=,rss=,comm='],
                            capture_output=True, text=True, errors='replace', timeout=1.5,
                            # ps prints "0,1" for CPU under a decimal-comma locale, which float() rejects.
                            env=dict(os.environ, LC_ALL='C'))
    if result.returncode:
        raise ValueError(result.stderr.strip() or 'Could not read the process list')
    processes = []
    for line in result.stdout.splitlines():
        fields = line.split(None, 3)
        if len(fields) != 4:
            continue
        pid, cpu, rss, command = fields
        try:
            processes.append((float(cpu), int(pid), int(rss), command.rsplit('/', 1)[-1]))
        except ValueError:
            continue
    count = 0
    for cpu, pid, rss, name in sorted(processes, reverse=True):
        if pid <= 1 or (query and query not in name.casefold()):
            continue
        print(json.dumps({'title': name, 'subtitle': f'PID {pid} · {cpu:g}% CPU · {rss // 1024} MB',
                          'arg': str(pid), 'actionLabel': 'Force Quit Process',
                          'confirmation': f'Force quit {name} (PID {pid})? Unsaved work may be lost. This stops the process immediately.'}))
        count += 1
        if count == 40:
            break


if __name__ == '__main__':
    try:
        main()
    except (OSError, ValueError, IndexError, subprocess.TimeoutExpired) as error:
        print(str(error), file=sys.stderr)
        sys.exit(1)
