commit 2d25f2cd6c9f9d466d17c03d49d3c63cef601ec9 Spenser Truex <truex@equwal.com> 2026-09-20 22:29:48 -0700 macOS: a portable sbm.app in a DMG contrib/macos/build-dmg.sh makes sbm-VERSION.dmg. sbm.app contains bm, the bm-* tools and fzf for Intel and Apple silicon. It opens bm in a Terminal window. The app has an ad-hoc signature only.
.gitignore | 1 + README | 21 ++++++++++++++++ contrib/macos/Info.plist | 28 +++++++++++++++++++++ contrib/macos/build-dmg.sh | 62 ++++++++++++++++++++++++++++++++++++++++++++++ contrib/macos/sbm | 14 +++++++++++ contrib/macos/sbm-run | 12 +++++++++ 6 files changed, 138 insertions(+)
diff --git a/.gitignore b/.gitignore index 192f813..dca7fc0 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ tags.* bm bmks sbm-*-setup.exe +sbm-*.dmg diff --git a/README b/README index 8a8ddc0..119d66f 100644 --- a/README +++ b/README @@ -232,6 +232,27 @@ such as /dev/null. To remove sbm, use Apps in the Windows settings. The uninstaller keeps your bookmarks. contrib/windows/build-installer.sh makes the installer with NSIS. +== macOS == +Get sbm-VERSION.dmg from a release on GitHub, and drag sbm.app to +Applications. The app contains bm, the bm-* tools and fzf, so it needs no +other software. sbm.app opens bm in a Terminal window. The first time, macOS +asks if sbm can control Terminal. + +The app has no signature from a registered developer, so macOS stops it the +first time. To open it, use Open Anyway in System Settings, Privacy & +Security. Or remove the quarantine attribute: + + xattr -dr com.apple.quarantine /Applications/sbm.app + +To open sbm with a key, make a shortcut with the action Open App in the +Shortcuts app, and give it a keyboard shortcut. macOS has function keys up +to F20. To use the tools in a shell, add these lines to ~/.zprofile: + + PATH=/Applications/sbm.app/Contents/Resources/bin:$PATH + export SBM_OPEN=open SBM_COPY=pbcopy SBM_PASTE=pbpaste + +contrib/macos/build-dmg.sh makes the image on a Mac. + == Tests == make check diff --git a/contrib/macos/Info.plist b/contrib/macos/Info.plist new file mode 100644 index 0000000..57cdcd6 --- /dev/null +++ b/contrib/macos/Info.plist @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>en</string> + <key>CFBundleDisplayName</key> + <string>sbm</string> + <key>CFBundleExecutable</key> + <string>sbm</string> + <key>CFBundleIdentifier</key> + <string>com.equwal.sbm</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>sbm</string> + <key>CFBundlePackageType</key> + <string>APPL</string> + <key>CFBundleShortVersionString</key> + <string>@VERSION@</string> + <key>CFBundleVersion</key> + <string>@VERSION@</string> + <key>LSMinimumSystemVersion</key> + <string>11.0</string> + <key>NSAppleEventsUsageDescription</key> + <string>sbm opens bm in a Terminal window.</string> +</dict> +</plist> diff --git a/contrib/macos/build-dmg.sh b/contrib/macos/build-dmg.sh new file mode 100755 index 0000000..5eb2577 --- /dev/null +++ b/contrib/macos/build-dmg.sh @@ -0,0 +1,62 @@ +#!/bin/sh + +# build-dmg.sh: make sbm-VERSION.dmg, the portable macOS edition, in the top +# directory of the source. Run it on macOS: +# +# sh contrib/macos/build-dmg.sh +# +# The image holds sbm.app. The app contains bm, the bm-* tools and fzf, so it +# needs no other software. The script gets fzf from the fzf release on +# GitHub. It stops if the SHA-256 sum of a download is not the expected one. + +set -e + +fzf_version=0.74.4 +fzf_amd64_sum=2d392b50be66e2ab104ccd52a6072df692b1f9b9c5b449a9c098de885f32c4c5 +fzf_arm64_sum=4f6a113bfc0c7959e0005c78d566a51afc4fcefc956f43735c62a9deb19e92ae + +here=$(cd "$(dirname "$0")" && pwd) +top=$(cd "$here/../.." && pwd) +version=$(sed -n 's/^VERSION=//p' "$top/config.mk") +out=$top/sbm-$version.dmg + +work=${TMPDIR:-/tmp}/sbm-dmg.$$ +mkdir "$work" +trap 'rm -rf "$work"' EXIT INT TERM +app=$work/root/sbm.app +mkdir -p "$app/Contents/MacOS" + +make -s -C "$top" install PREFIX="$app/Contents/Resources" >/dev/null +cp "$here/sbm" "$app/Contents/MacOS/sbm" +cp "$here/sbm-run" "$app/Contents/Resources/sbm-run" +chmod 755 "$app/Contents/MacOS/sbm" "$app/Contents/Resources/sbm-run" +sed "s/@VERSION@/$version/g" "$here/Info.plist" > "$app/Contents/Info.plist" +plutil -lint "$app/Contents/Info.plist" >/dev/null + +url=https://github.com/junegunn/fzf/releases/download/v$fzf_version +for arch in amd64 arm64; do + curl -fsSL -o "$work/fzf-$arch.tar.gz" \ + "$url/fzf-$fzf_version-darwin_$arch.tar.gz" +done +shasum -a 256 -c >/dev/null <<EOF +$fzf_amd64_sum $work/fzf-amd64.tar.gz +$fzf_arm64_sum $work/fzf-arm64.tar.gz +EOF +for arch in amd64 arm64; do + mkdir "$work/$arch" + tar -xzf "$work/fzf-$arch.tar.gz" -C "$work/$arch" +done +# One fzf for Intel and Apple silicon. +lipo -create -output "$app/Contents/Resources/bin/fzf" \ + "$work/amd64/fzf" "$work/arm64/fzf" +curl -fsSL -o "$app/Contents/Resources/fzf-LICENSE.txt" \ + "https://raw.githubusercontent.com/junegunn/fzf/v$fzf_version/LICENSE" + +# The app has no signature from a registered developer. An ad-hoc signature +# still lets macOS find a damaged app. +codesign --force --deep --sign - "$app" + +ln -s /Applications "$work/root/Applications" +hdiutil create -quiet -volname "sbm $version" -srcfolder "$work/root" \ + -ov -format UDZO "$out" +printf '%s\n' "$out" diff --git a/contrib/macos/sbm b/contrib/macos/sbm new file mode 100755 index 0000000..91094f8 --- /dev/null +++ b/contrib/macos/sbm @@ -0,0 +1,14 @@ +#!/bin/sh + +# sbm: the program of sbm.app. It opens a Terminal window that runs +# sbm-run. The first time, macOS asks if sbm can control Terminal. + +run=$(cd "$(dirname "$0")/../Resources" && pwd)/sbm-run +exec osascript \ + -e 'on run argv' \ + -e 'tell application "Terminal"' \ + -e 'activate' \ + -e 'do script (quoted form of item 1 of argv) & "; exit 0"' \ + -e 'end tell' \ + -e 'end run' \ + "$run" diff --git a/contrib/macos/sbm-run b/contrib/macos/sbm-run new file mode 100755 index 0000000..2fb89c6 --- /dev/null +++ b/contrib/macos/sbm-run @@ -0,0 +1,12 @@ +#!/bin/sh + +# sbm-run: run bm with the tools in sbm.app. bm opens URLs in the default +# browser and uses the clipboard of macOS. Settings in the environment win. + +bin=$(cd "$(dirname "$0")/bin" && pwd) +PATH=$bin:$PATH +SBM_OPEN=${SBM_OPEN:-open} +SBM_COPY=${SBM_COPY:-pbcopy} +SBM_PASTE=${SBM_PASTE:-pbpaste} +export PATH SBM_OPEN SBM_COPY SBM_PASTE +exec bm "$@"