forked from NotAShelf/beer
config: live reload on SIGUSR1
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: I2549feccf6eb3a48ea39dbf0e370e0c46a6a6964
This commit is contained in:
parent
9a680ab42e
commit
0ecda1b5ce
2 changed files with 49 additions and 2 deletions
|
|
@ -62,5 +62,5 @@ fn run(cli: Cli) -> anyhow::Result<ExitCode> {
|
||||||
|
|
||||||
let config = Config::load(cli.config.as_deref());
|
let config = Config::load(cli.config.as_deref());
|
||||||
tracing::info!("starting beer");
|
tracing::info!("starting beer");
|
||||||
wayland::run(config)
|
wayland::run(config, cli.config)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -170,7 +170,7 @@ const DEFAULT_W: u32 = 800;
|
||||||
const DEFAULT_H: u32 = 600;
|
const DEFAULT_H: u32 = 600;
|
||||||
|
|
||||||
/// Run a single window until it is closed, returning the shell's exit code.
|
/// Run a single window until it is closed, returning the shell's exit code.
|
||||||
pub fn run(config: Config) -> anyhow::Result<ExitCode> {
|
pub fn run(config: Config, config_path: Option<std::path::PathBuf>) -> anyhow::Result<ExitCode> {
|
||||||
let conn = Connection::connect_to_env().context("connect to Wayland compositor")?;
|
let conn = Connection::connect_to_env().context("connect to Wayland compositor")?;
|
||||||
let (globals, event_queue) =
|
let (globals, event_queue) =
|
||||||
registry_queue_init(&conn).context("initialize Wayland registry")?;
|
registry_queue_init(&conn).context("initialize Wayland registry")?;
|
||||||
|
|
@ -254,6 +254,7 @@ pub fn run(config: Config) -> anyhow::Result<ExitCode> {
|
||||||
session: None,
|
session: None,
|
||||||
title: None,
|
title: None,
|
||||||
config,
|
config,
|
||||||
|
config_path,
|
||||||
bindings,
|
bindings,
|
||||||
font_size,
|
font_size,
|
||||||
fullscreen: false,
|
fullscreen: false,
|
||||||
|
|
@ -286,6 +287,19 @@ pub fn run(config: Config) -> anyhow::Result<ExitCode> {
|
||||||
tracing::warn!("register blink timer: {err}");
|
tracing::warn!("register blink timer: {err}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SIGUSR1 reloads the config in place.
|
||||||
|
match calloop::signals::Signals::new(&[calloop::signals::Signal::SIGUSR1]) {
|
||||||
|
Ok(signals) => {
|
||||||
|
let registered = event_loop
|
||||||
|
.handle()
|
||||||
|
.insert_source(signals, |_, _, app: &mut App| app.reload_config());
|
||||||
|
if let Err(err) = registered {
|
||||||
|
tracing::warn!("register signal source: {err}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(err) => tracing::warn!("install SIGUSR1 handler: {err}"),
|
||||||
|
}
|
||||||
|
|
||||||
// Each iteration blocks until an event (PTY output, input, configure, frame
|
// Each iteration blocks until an event (PTY output, input, configure, frame
|
||||||
// callback, blink) arrives, then presents at most one frame; bursts of PTY
|
// callback, blink) arrives, then presents at most one frame; bursts of PTY
|
||||||
// output between frame callbacks coalesce into a single repaint.
|
// output between frame callbacks coalesce into a single repaint.
|
||||||
|
|
@ -380,6 +394,8 @@ struct App {
|
||||||
title: Option<String>,
|
title: Option<String>,
|
||||||
/// The active user configuration.
|
/// The active user configuration.
|
||||||
config: Config,
|
config: Config,
|
||||||
|
/// Path the config was loaded from, for SIGUSR1 live reload.
|
||||||
|
config_path: Option<std::path::PathBuf>,
|
||||||
/// Resolved key/text bindings.
|
/// Resolved key/text bindings.
|
||||||
bindings: crate::bindings::Bindings,
|
bindings: crate::bindings::Bindings,
|
||||||
/// Current font size in pixels (changed by font-resize bindings).
|
/// Current font size in pixels (changed by font-resize bindings).
|
||||||
|
|
@ -575,6 +591,37 @@ impl App {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Re-read the config file and apply it in place (SIGUSR1).
|
||||||
|
fn reload_config(&mut self) {
|
||||||
|
let new = Config::load(self.config_path.as_deref());
|
||||||
|
self.bindings =
|
||||||
|
crate::bindings::Bindings::from_config(&new.key_bindings, &new.text_bindings);
|
||||||
|
self.renderer.set_padding(new.main.pad_x, new.main.pad_y);
|
||||||
|
if new.main.font != self.config.main.font || new.main.font_size != self.font_size {
|
||||||
|
match self.renderer.set_font(&new.main.font, new.main.font_size) {
|
||||||
|
Ok(()) => self.font_size = new.main.font_size,
|
||||||
|
Err(err) => tracing::warn!("reload font: {err:#}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(session) = self.session.as_mut() {
|
||||||
|
session
|
||||||
|
.term
|
||||||
|
.set_theme(crate::theme::Theme::from_config(&new.colors));
|
||||||
|
let grid = session.term.grid_mut();
|
||||||
|
grid.set_word_delimiters(new.main.word_delimiters.clone());
|
||||||
|
grid.set_scrollback_cap(new.scrollback.lines);
|
||||||
|
if let Some(shape) = cursor_shape_from(new.cursor.style.as_deref()) {
|
||||||
|
grid.set_cursor_shape(shape);
|
||||||
|
}
|
||||||
|
grid.set_cursor_blink(new.cursor.blink);
|
||||||
|
}
|
||||||
|
self.config = new;
|
||||||
|
self.frames.clear();
|
||||||
|
self.resize_grid();
|
||||||
|
self.needs_draw = true;
|
||||||
|
tracing::info!("config reloaded");
|
||||||
|
}
|
||||||
|
|
||||||
/// Re-rasterize the font at `new_size`, then re-derive the grid geometry.
|
/// Re-rasterize the font at `new_size`, then re-derive the grid geometry.
|
||||||
fn change_font_size(&mut self, new_size: u32) {
|
fn change_font_size(&mut self, new_size: u32) {
|
||||||
let new_size = new_size.clamp(6, 200);
|
let new_size = new_size.clamp(6, 200);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue