Brewfile を自動生成するようにした

homebrew で入れているアプリが多岐にわたっており、管理が難しくなっていた。 そこで、Brewfile を自動生成するようにした。

今入っているアプリを Brewfile に書き出してくれる。 description も一緒に出力するようにしたので、何のために入れてるアプリかがわかりやすくなった。

#!/usr/bin/python3

import os
import subprocess
import json
import re

def get_formula_info(packages):
    """Retrieve name and description for formula packages using `brew info --json`."""
    cmd = ["brew", "info", "--json"] + packages
    try:
        result = subprocess.run(cmd, capture_output=True, text=True, check=True)
        data = json.loads(result.stdout)
        return [(item["name"], item.get("desc", "No description available")) for item in data]
    except subprocess.CalledProcessError:
        return []

def get_cask_info(packages):
    """Retrieve name and description for cask packages using `brew info --cask`."""
    cmd = ["brew", "info", "--cask"] + packages
    try:
        result = subprocess.run(cmd, capture_output=True, text=True, check=True)
        lines = result.stdout.splitlines()
        casks = []
        current_cask = {}
        for index, line in enumerate(lines):
            if line.startswith("==> "):
                if ':' in line:
                    current_cask["name"] = line.split(':')[0].split(' ')[1]
                elif line.startswith("==> Description"):
                    current_cask["desc"] = lines[index + 1].strip()
                    casks.append([current_cask['name'], current_cask['desc']])
                    current_cask = {}
        return casks
    except subprocess.CalledProcessError:
        return []

def get_mas_info(lines):
    """

    sample output of the mas list command:

        1289197285  MindNode        (2023.6)
        539883307   LINE            (9.5.0)
        1289583905  Pixelmator Pro  (3.6.14)
    """
    for line in lines:
        id_, name = re.match(r"(\d+)\s+(.+?)\s+\(.+?\)", line).groups()
        yield name, id_

def generate_cask(script):
    script.write("# -----------------------------------'\n")
    script.write("# Installing casks...\n")
    script.write("# -----------------------------------'\n\n")
    cask_list = subprocess.getoutput("brew list --cask -1").splitlines()
    cask_info = get_cask_info(cask_list)
    for name, desc in cask_info:
        script.write(f"# {desc}\n")
        script.write(f"cask '{name}'\n\n")
    script.write("\n")

def generate_formula(script):
        script.write("# -----------------------------------'\n")
        script.write("# Installing formulae...\n")
        script.write("# -----------------------------------'\n\n")
        formula_list = subprocess.getoutput("brew leaves").splitlines()
        formula_info = get_formula_info(formula_list)
        for name, desc in formula_info:
            script.write(f"# {desc}\n")
            script.write(f"brew '{name}'\n\n")

def generate_mas(script):
        script.write("# -----------------------------------'\n")
        script.write("# Installing mas(Mac app store)...\n")
        script.write("# -----------------------------------'\n\n")
        mas_list = subprocess.getoutput("mas list").splitlines()
        mas_info = get_mas_info(mas_list)
        for name, id_ in mas_info:
            script.write(f"mas '{name}', id: {id_}\n\n")

def generate_script():
    """Generate a reinstallation script for Homebrew packages and casks."""
    output_script = "Brewfile"

    with open(output_script, "w") as script:
        generate_cask(script)
        generate_formula(script)
        generate_mas(script)

    print(f"Reinstallation script has been generated: {output_script}")

if __name__ == "__main__":
    generate_script()

生成結果は以下のようになった。

# -----------------------------------'
# Installing casks...
# -----------------------------------'

# Enable Windows-like alt-tab
cask 'alt-tab'

# Japanese input method editor (IME) produced by JustSystems
cask 'atok'

# Utility that prevents the system from going to sleep
cask 'caffeine'

# Screen capturing tool
cask 'cleanshot'

# Plain-text editor for web pages, program source codes and more
cask 'coteditor'

# App to build and share containerised applications and microservices
cask 'docker'

# Web browser
cask 'firefox'

# Web browser
cask 'google-chrome'

# Keyboard shortcuts for every button on your screen
cask 'homerow'

# Keyboard customiser
cask 'karabiner-elements'

# Control your tools with a few keystrokes
cask 'raycast'

# Team communication and collaboration software
cask 'slack'

# Configuration application for the Ultimate Hacking Keyboard
cask 'uhk-agent'

# Open-source code editor
cask 'visual-studio-code'

# Web browser with built-in email client focusing on customization and control
cask 'vivaldi'

# GPU-accelerated cross-platform terminal emulator and multiplexer
cask 'wezterm'


# -----------------------------------'
# Installing formulae...
# -----------------------------------'

# Yet another cross-platform graphical process/system monitor
brew 'bottom'

# GNU File, Shell, and Text utilities
brew 'coreutils'

# Get, unpack, build, and install modules from CPAN
brew 'cpanminus'

# Cryptographic recipes and primitives for Python
brew 'cryptography'

# User-friendly command-line shell for UNIX-like operating systems
brew 'fish'

# Distributed revision control system
brew 'git'

# Git extension for versioning large files
brew 'git-lfs'

# GNU Pretty Good Privacy (PGP) package
brew 'gnupg'

# Graph visualization software from AT&T and Bell Labs
brew 'graphviz'

# Tools and libraries to manipulate images in many formats
brew 'imagemagick'

# Interactive computing in Python
brew 'ipython'

# Manage your Java environment
brew 'jenv'

# Lightweight and flexible command-line JSON processor
brew 'jq'

# Powerful multi-lingual file viewer/grep
brew 'lv'

# Mac App Store command-line interface
brew 'mas'

# Network grep
brew 'ngrep'

# Network Kanji code conversion Filter (NKF)
brew 'nkf'

# Platform built on V8 to build network applications
brew 'node'

# Manage multiple NodeJS versions
brew 'nodenv'

# Safe, concurrent, practical language
brew 'rust'

# Rust toolchain installer
brew 'rustup'

# Code-search similar to ack
brew 'the_silver_searcher'

# Terminal multiplexer
brew 'tmux'

# Display directories as trees (with optional color/HTML output)
brew 'tree'

# Vi 'workalike' with many additional features
brew 'vim'

# Pager/text based browser
brew 'w3m'

# UNIX shell (command interpreter)
brew 'zsh'

# -----------------------------------'
# Installing mas(Mac app store)...
# -----------------------------------'

mas 'MindNode', id: 1289197285

mas 'LINE', id: 539883307

mas 'Pixelmator Pro', id: 1289583905

これを dotfiles のレポジトリで管理するようにした。便利。

Published: 2025-01-01(Wed) 13:12