aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/homebrew/slosh.rb
blob: fa848e3a1ac137312a0a06d956f8fc628febe4cf (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# slosh — Homebrew formula (a *formula*, not a cask: casks are for prebuilt
# .app/.pkg/.dmg drops, formulae are for things brew builds and puts in bin).
#
# This file is the source of truth. `contrib/brew-release` rewrites the three
# stanzas below (url/version/sha256) for a new commit or tag and copies the
# result into the tap repo, which is what users actually tap:
#
#     brew tap sl0p-foo/slosh
#     brew install slosh
#
# Try it without publishing anything:
#
#     brew install --build-from-source contrib/homebrew/slosh.rb
class Slosh < Formula
  desc "Terminal multiplexer with detachable sessions and programmable pane chrome"
  homepage "https://sl0p.foo"
  # GitHub's archive of a commit is deterministic per ref: same ref, same
  # bytes, so the sha256 below stays honest. Pinned to a full commit id rather
  # than a branch, because a branch tarball changes under you and brew would
  # keep the stale one.
  url "https://github.com/sl0p-foo/slosh/archive/c861d1d0fb80d6cc50d34565362767609580b0bd.tar.gz"
  version "0.1.8"
  sha256 "a40bf0af3f1a144b89de6143b3e2f4869ecd397c4704a02b93950d5e2c40b8fb"
  head "https://github.com/sl0p-foo/slosh.git", branch: "master"

  # zig is the whole toolchain: it compiles the C, builds the vendored
  # libghostty-vt, and links it statically. Nothing is needed at runtime, which
  # is why there is no `depends_on` without `=> :build`.
  #
  # Pinned to an exact minor, not plain "zig": the vendored libghostty-vt
  # rejects any mismatched major/minor outright (see src/build/zig.zig's
  # requireZig), so when homebrew-core moved "zig" to 0.17.0 every install
  # broke with "Your Zig version v0.17.0 does not meet the required build
  # version of v0.16.0". The pin has to be bumped in lockstep with
  # vendor/libghostty-vt.vendor.json's built_with_zig whenever we re-vendor.
  depends_on "zig@0.16" => :build

  def install
    # zig caches in ~/.cache/zig and ~/.zig-cache by default. Under brew that is
    # either a sandbox denial or pollution of the user's real cache, so both
    # caches go into the build directory and die with it.
    ENV["ZIG_GLOBAL_CACHE_DIR"] = buildpath/".zig-global-cache"
    ENV["ZIG_LOCAL_CACHE_DIR"] = buildpath/".zig-local-cache"

    # The pinned keg is keg-only, so it is deliberately absent from PATH and
    # from /opt/homebrew/opt/zig. Name it explicitly or the build picks up
    # whatever "zig" happens to be linked.
    args = ["ZIG=#{formula_opt_bin("zig@0.16")}/zig"]
    # In a snapshot tarball there is no .git, so the Makefile's `git describe`
    # would bake in "unknown" and `slosh --version` could not tell you which
    # build you are looking at. Hand it the commit the tarball came from.
    args << "GITDESC=#{version.to_s.split("-").last}" unless build.head?

    system "make", "vendor", *args
    system "make", "all", *args

    # Deliberately not `make install`: the formula must be able to build any
    # commit, including ones older than that target, and the layout is three
    # lines here. `make install PREFIX=...` exists for everyone not using brew
    # and puts the same files in the same places.
    bin.install "build/slosh"
    # Guarded because the formula must be able to build any commit, including
    # ones older than the manpages.
    man1.install "docs/slosh.1" if File.exist?("docs/slosh.1")
    man5.install "docs/slosh.5" if File.exist?("docs/slosh.5")
    pkgshare.install "config/config.kdl", "config/example.layout"
    %w[themes chrome shaders].each do |d|
      pkgshare.install Dir["contrib/#{d}"] if File.directory?("contrib/#{d}")
    end
    doc.install "README.md"
    doc.install Dir["docs/*.md"]
  end

  def caveats
    <<~EOS
      Example configuration, themes, chrome and shaders are installed in:
        #{opt_share}/slosh

      Start from the shipped config:
        mkdir -p ~/.config/slosh && cp #{opt_share}/slosh/config.kdl ~/.config/slosh/

      Then: slosh          (attach to session "main", creating it if needed)
            C-a ?          (the keys)   C-a p   (every command by name)
    EOS
  end

  test do
    # The binary knows its own version, and it is the version brew installed.
    # Derived from `version`, never hardcoded: a literal goes stale at the next
    # release and fails a build that is otherwise perfectly good.
    out = shell_output("#{bin}/slosh --version")
    assert_match(/^slosh \S+/, out)
    # A HEAD build reports `git describe`, which is not the formula version.
    assert_match "slosh #{version}", out unless build.head?

    # The configuration we ship must parse with the binary we ship.
    assert_match "ok", shell_output("#{bin}/slosh --check #{share}/slosh/config.kdl")

    # And it composes a real screen headlessly: no tty, no session, no socket.
    # This exercises the vendored terminal core, the layout and the renderer.
    screen = shell_output("#{bin}/slosh --headless --cols 40 --rows 12 -- " \
                          "/bin/sh -c 'echo hello-brew'")
    assert_match "hello-brew", screen
    assert_match "pane 1/1", screen
  end
end