Skip to content

Commit

Permalink
Add option to run command on bell
Browse files Browse the repository at this point in the history
  • Loading branch information
kchibisov committed Jun 14, 2020
1 parent 6ee8717 commit 34b4d87
Show file tree
Hide file tree
Showing 10 changed files with 234 additions and 67 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Font fallback on Windows
- Support for Fontconfig embolden and matrix options
- Opt-out compilation flag `winpty` to disable WinPTY support
- Option to run command on bell which can be set in `bell.command`

### Changed

Expand Down
65 changes: 40 additions & 25 deletions alacritty.yml
Expand Up @@ -245,31 +245,46 @@
#
#indexed_colors: []

# Visual Bell
#
# Any time the BEL code is received, Alacritty "rings" the visual bell. Once
# rung, the terminal background will be set to white and transition back to the
# default background color. You can control the rate of this transition by
# setting the `duration` property (represented in milliseconds). You can also
# configure the transition function by setting the `animation` property.
#
# Values for `animation`:
# - Ease
# - EaseOut
# - EaseOutSine
# - EaseOutQuad
# - EaseOutCubic
# - EaseOutQuart
# - EaseOutQuint
# - EaseOutExpo
# - EaseOutCirc
# - Linear
#
# Specifying a `duration` of `0` will disable the visual bell.
#visual_bell:
# animation: EaseOutExpo
# duration: 0
# color: '#ffffff'
# Bell
#
# The bell is triggered every time BEL escape sequence is received.
#bell:
# Visual Bell Animation
#
# Animation effect for flashing the screen when the visual bell is rung.
#
# Values for `animation`:
# - Ease
# - EaseOut
# - EaseOutSine
# - EaseOutQuad
# - EaseOutCubic
# - EaseOutQuart
# - EaseOutQuint
# - EaseOutExpo
# - EaseOutCirc
# - Linear
#animation: EaseOutExpo

# Duration of the visual bell flash. A `duration` of `0` will disable the
# visual bell animation.
#duration: 0

# Visual bell animation color.
#color: '#ffffff'

# Bell Command
#
# This program is executed whenever the bell is rung.
#
# When set to `command: None`, bell command will be disabled completely.
#
# Example:
# command:
# program: notify-send
# args: ["Hello, World!"]
#
#command: None

# Background opacity
#
Expand Down
7 changes: 7 additions & 0 deletions alacritty/src/config/mod.rs
Expand Up @@ -217,6 +217,13 @@ fn print_deprecation_warnings(config: &Config) {
the config"
);
}

if config.visual_bell.is_some() {
warn!(
target: LOG_TARGET_CONFIG,
"Config visual_bell has been deprecated; please use bell instead"
)
}
}

#[cfg(test)]
Expand Down
2 changes: 1 addition & 1 deletion alacritty/src/display.rs
Expand Up @@ -478,7 +478,7 @@ impl Display {
0.,
size_info.width,
size_info.height,
config.visual_bell.color,
config.bell().color,
visual_bell_intensity as f32,
);
rects.push(visual_bell_rect);
Expand Down
12 changes: 11 additions & 1 deletion alacritty/src/event.rs
Expand Up @@ -573,7 +573,17 @@ impl<N: Notify + OnResize> Processor<N> {
},
Event::Title(title) => processor.ctx.window.set_title(&title),
Event::Wakeup => processor.ctx.terminal.dirty = true,
Event::Urgent => {
Event::Bell => {
if let Some(command) = processor.ctx.config.bell().command.as_ref() {
let args = command.args().to_vec();

match start_daemon(command.program(), &args) {
Ok(_) => debug!("Launched {} with args {:?}", command.program(), args),
Err(_) => {
warn!("Unable to launch {} with args {:?}", command.program(), args)
},
}
}
processor.ctx.window.set_urgent(!processor.ctx.terminal.is_focused)
},
Event::ConfigReload(path) => Self::reload_config(&path, processor),
Expand Down
105 changes: 105 additions & 0 deletions alacritty_terminal/src/config/bell.rs
@@ -0,0 +1,105 @@
use std::time::Duration;

use log::error;
use serde::{Deserialize, Deserializer};
use serde_yaml::Value;

use crate::config::{failure_default, Program, LOG_TARGET_CONFIG};
use crate::term::color::Rgb;

const DEFAULT_BELL_COLOR: Rgb = Rgb { r: 255, g: 255, b: 255 };

#[serde(default)]
#[derive(Deserialize, Clone, Debug, PartialEq, Eq)]
pub struct BellConfig {
/// Visual bell animation function.
#[serde(deserialize_with = "failure_default")]
pub animation: BellAnimation,

/// Visual bell duration in milliseconds.
#[serde(deserialize_with = "failure_default")]
duration: u16,

// FIXME RGB deserialization always successedes and uses #000000 color. However it should
// fallback to a proper color. So it should be reworked either with
// https://github.com/alacritty/alacritty/pull/3507 or after that PR will land.
/// Visual bell flash color.
#[serde(deserialize_with = "failure_default")]
pub color: Rgb,

/// Command to run on bell.
#[serde(deserialize_with = "deserialize_command")]
pub command: Option<Program>,
}

impl Default for BellConfig {
fn default() -> Self {
Self {
animation: Default::default(),
duration: Default::default(),
color: DEFAULT_BELL_COLOR,
command: Default::default(),
}
}
}

impl BellConfig {
/// Visual bell duration in milliseconds.
#[inline]
pub fn duration(&self) -> Duration {
Duration::from_millis(u64::from(self.duration))
}
}

fn deserialize_command<'a, D>(deserializer: D) -> std::result::Result<Option<Program>, D::Error>
where
D: Deserializer<'a>,
{
// Deserialize to generic value.
let val = Value::deserialize(deserializer)?;

// Accept `None` to disable the bell command.
if val.as_str().filter(|v| v.to_lowercase() == "none").is_some() {
return Ok(None);
}

match <Option<Program>>::deserialize(val) {
Ok(command) => Ok(command),
Err(err) => {
error!(target: LOG_TARGET_CONFIG, "Problem with config: {}; not using anything", err);
Ok(None)
},
}
}

/// `VisualBellAnimations` are modeled after a subset of CSS transitions and Robert
/// Penner's Easing Functions.
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq)]
pub enum BellAnimation {
// CSS animation.
Ease,
// CSS animation.
EaseOut,
// Penner animation.
EaseOutSine,
// Penner animation.
EaseOutQuad,
// Penner animation.
EaseOutCubic,
// Penner animation.
EaseOutQuart,
// Penner animation.
EaseOutQuint,
// Penner animation.
EaseOutExpo,
// Penner animation.
EaseOutCirc,
// Penner animation.
Linear,
}

impl Default for BellAnimation {
fn default() -> Self {
BellAnimation::EaseOutExpo
}
}
17 changes: 13 additions & 4 deletions alacritty_terminal/src/config/mod.rs
Expand Up @@ -6,20 +6,20 @@ use log::error;
use serde::{Deserialize, Deserializer};
use serde_yaml::Value;

mod bell;
mod colors;
mod debug;
mod font;
mod scrolling;
mod visual_bell;
mod window;

use crate::ansi::{CursorStyle, NamedColor};

pub use crate::config::bell::{BellAnimation, BellConfig};
pub use crate::config::colors::Colors;
pub use crate::config::debug::Debug;
pub use crate::config::font::{Font, FontDescription};
pub use crate::config::scrolling::Scrolling;
pub use crate::config::visual_bell::{VisualBellAnimation, VisualBellConfig};
pub use crate::config::window::{Decorations, Dimensions, StartupMode, WindowConfig, DEFAULT_NAME};
use crate::term::color::Rgb;

Expand Down Expand Up @@ -70,9 +70,9 @@ pub struct Config<T> {
#[serde(default, deserialize_with = "failure_default")]
pub config_path: Option<PathBuf>,

/// Visual bell configuration.
/// Bell configuration.
#[serde(default, deserialize_with = "failure_default")]
pub visual_bell: VisualBellConfig,
bell: BellConfig,

/// Use dynamic title.
#[serde(default, deserialize_with = "failure_default")]
Expand Down Expand Up @@ -115,6 +115,10 @@ pub struct Config<T> {
#[serde(skip)]
pub hold: bool,

// TODO: DEPRECATED
#[serde(default, deserialize_with = "failure_default")]
pub visual_bell: Option<BellConfig>,

// TODO: REMOVED
#[serde(default, deserialize_with = "failure_default")]
pub tabspaces: Option<usize>,
Expand Down Expand Up @@ -201,6 +205,11 @@ impl<T> Config<T> {
pub fn background_opacity(&self) -> f32 {
self.background_opacity.0 as f32
}

#[inline]
pub fn bell(&self) -> &BellConfig {
self.visual_bell.as_ref().unwrap_or(&self.bell)
}
}

#[serde(default)]
Expand Down
50 changes: 36 additions & 14 deletions alacritty_terminal/src/config/visual_bell.rs
Expand Up @@ -2,47 +2,73 @@ use std::time::Duration;

use serde::Deserialize;

use crate::config::failure_default;
use crate::config::{failure_default, Program};
use crate::term::color::Rgb;

const DEFAULT_BELL_COLOR: Rgb = Rgb {r: 255, g: 255, b: 255};

#[serde(default)]
#[derive(Deserialize, Clone, Debug, PartialEq, Eq)]
pub struct VisualBellConfig {
pub struct BellConfig {
/// Visual bell animation function.
#[serde(deserialize_with = "failure_default")]
pub animation: VisualBellAnimation,

/// Visual bell duration in milliseconds.
#[serde(deserialize_with = "failure_default")]
pub duration: u16,
duration: u16,

/// Visual bell flash color.
#[serde(deserialize_with = "failure_default")]
#[serde(deserialize_with = "deserialize_bell_color")]
pub color: Rgb,

/// Command to run on bell.
pub command: Option<Program>
}

impl Default for VisualBellConfig {
impl Default for BellConfig {
fn default() -> VisualBellConfig {
VisualBellConfig {
animation: Default::default(),
duration: Default::default(),
color: default_visual_bell_color(),
color: DEFAULT_BELL_COLOR,
command: Default::default(),
}
}
}

impl VisualBellConfig {
impl BellConfig {
/// Visual bell duration in milliseconds.
#[inline]
pub fn duration(&self) -> Duration {
Duration::from_millis(u64::from(self.duration))
}
}

fn deserialize_cursor_thickness<'a, D>(deserializer: D) -> Result<Rgb, D::Error>
where
D: Deserializer<'a>,
{
let value = Value::deserialize(deserializer)?;
match Percentage::deserialize(value) {
Ok(value) => Ok(value),
Err(err) => {
error!(
target: LOG_TARGET_CONFIG,
"Problem with config: {}, using default bell color {}",
err,
DEFAULT_BELL_COLOR
);

Ok(Percentage::new(DEFAULT_BELL_COLOR))
},
}
}

/// `VisualBellAnimations` are modeled after a subset of CSS transitions and Robert
/// Penner's Easing Functions.
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq)]
pub enum VisualBellAnimation {
pub enum BellAnimation {
// CSS animation.
Ease,
// CSS animation.
Expand All @@ -65,12 +91,8 @@ pub enum VisualBellAnimation {
Linear,
}

impl Default for VisualBellAnimation {
impl Default for BellAnimation {
fn default() -> Self {
VisualBellAnimation::EaseOutExpo
BellAnimation::EaseOutExpo
}
}

fn default_visual_bell_color() -> Rgb {
Rgb { r: 255, g: 255, b: 255 }
}

0 comments on commit 34b4d87

Please sign in to comment.