brewery
notashelf /
56907b4115097be9b5164486b21bd80e353e0b28

beer

public

A terminal worth pouring time into

Star0tarball
clone
ssh://git@git.notashelf.dev:33/notashelf/beer.git

Commit 56907b411509

tarball

NotAShelf <raf@notashelf.dev> · 2026-06-24 12:36 UTC

unverified2 files changed+21-9
pty: propagate the shell's exit status

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I9f33a222a19794b6ad2910fb6029796f6a6a6964
diff --git a/src/main.rs b/src/main.rsindex 5981dc1..e9e3a15 100644--- a/src/main.rs+++ b/src/main.rs@@ -23,7 +23,7 @@ struct Cli { fn main() -> ExitCode {     init_logging();     match run(Cli::parse()) {-        Ok(()) => ExitCode::SUCCESS,+        Ok(code) => code,         Err(err) => {             tracing::error!("{err:#}");             eprintln!("beer: {err:#}");@@ -45,10 +45,9 @@ fn init_logging() {         .init(); } -fn run(cli: Cli) -> anyhow::Result<()> {+fn run(cli: Cli) -> anyhow::Result<ExitCode> {     if cli.server {-        tracing::info!("starting beer server");-        todo!("server mode")+        anyhow::bail!("server mode is not implemented yet");     }      tracing::info!("starting beer");diff --git a/src/wayland.rs b/src/wayland.rsindex ec570c2..dd4f8f7 100644--- a/src/wayland.rs+++ b/src/wayland.rs@@ -4,6 +4,8 @@ //! event loop, so the PTY master fd and timers share one loop.  use std::os::fd::OwnedFd;+use std::os::unix::process::ExitStatusExt;+use std::process::ExitCode; use std::time::Duration;  use anyhow::Context;@@ -45,8 +47,8 @@ const DEFAULT_H: u32 = 600; const FONT_FAMILY: &str = "monospace"; const FONT_SIZE_PX: u32 = 16; -/// Run a single window until it is closed.-pub fn run() -> anyhow::Result<()> {+/// Run a single window until it is closed, returning the shell's exit code.+pub fn run() -> anyhow::Result<ExitCode> {     let conn = Connection::connect_to_env().context("connect to Wayland compositor")?;     let (globals, event_queue) =         registry_queue_init(&conn).context("initialize Wayland registry")?;@@ -127,6 +129,7 @@ pub fn run() -> anyhow::Result<()> {         height: DEFAULT_H,         dirty: false,         exit: false,+        exit_code: ExitCode::SUCCESS,     };      while !app.exit {@@ -138,7 +141,7 @@ pub fn run() -> anyhow::Result<()> {             app.dirty = false;         }     }-    Ok(())+    Ok(app.exit_code) }  /// Columns and rows that fit a `width`×`height` px window at `metrics`.@@ -180,6 +183,8 @@ struct App {     /// The grid changed and the window needs repainting.     dirty: bool,     exit: bool,+    /// Exit code to return, taken from the shell when it exits.+    exit_code: ExitCode, }  impl App {@@ -213,10 +218,18 @@ impl App {         }     } -    /// The child shell has gone away; reap it and tear the window down.+    /// The child shell has gone away; reap it, capture its code, and tear the+    /// window down.     fn child_exited(&mut self) {         match self.pty.wait() {-            Ok(status) => tracing::info!("shell exited: {status}"),+            Ok(status) => {+                tracing::info!("shell exited: {status}");+                // Mirror the shell's status: its code, or 128+signal if killed.+                let code = status+                    .code()+                    .unwrap_or_else(|| 128 + status.signal().unwrap_or(0));+                self.exit_code = ExitCode::from(code as u8);+            }             Err(err) => tracing::warn!("reap shell: {err}"),         }         self.exit = true;