summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKirill Chibisov <contact@kchibisov.com>2020-07-10 22:32:44 +0300
committerGitHub <noreply@github.com>2020-07-10 22:32:44 +0300
commit8bd2c13490f8cb6ad6b0c1104f9586b3554efea2 (patch)
tree6909d3be00c72c3c5acdd173aa7f411a1bc6b445
parentb78f3d133960dad38ad21e808723e51661b59881 (diff)
downloadalacritty-8bd2c13490f8cb6ad6b0c1104f9586b3554efea2.tar.gz
alacritty-8bd2c13490f8cb6ad6b0c1104f9586b3554efea2.zip
Add option to run command on bell
Fixes #1528.
-rw-r--r--CHANGELOG.md2
-rw-r--r--Cargo.lock1
-rw-r--r--alacritty.yml67
-rw-r--r--alacritty/Cargo.toml1
-rw-r--r--alacritty/src/config/mod.rs7
-rw-r--r--alacritty/src/config/monitor.rs4
-rw-r--r--alacritty/src/daemon.rs (renamed from alacritty_terminal/src/util.rs)77
-rw-r--r--alacritty/src/display.rs2
-rw-r--r--alacritty/src/event.rs21
-rw-r--r--alacritty/src/input.rs9
-rw-r--r--alacritty/src/main.rs1
-rw-r--r--alacritty/src/renderer/mod.rs4
-rw-r--r--alacritty_terminal/src/config/bell.rs120
-rw-r--r--alacritty_terminal/src/config/mod.rs17
-rw-r--r--alacritty_terminal/src/config/visual_bell.rs76
-rw-r--r--alacritty_terminal/src/event.rs4
-rw-r--r--alacritty_terminal/src/event_loop.rs5
-rw-r--r--alacritty_terminal/src/lib.rs2
-rw-r--r--alacritty_terminal/src/term/color.rs10
-rw-r--r--alacritty_terminal/src/term/mod.rs53
-rw-r--r--alacritty_terminal/src/thread.rs11
21 files changed, 292 insertions, 202 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c19894cb..ed7783ed 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -30,6 +30,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Expanding existing selections using the right mouse button
- Support for `gopher` and `gemini` URLs
- Unicode 13 support
+- Option to run command on bell which can be set in `bell.command`
### Changed
@@ -48,6 +49,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- To use the cell's text color for selection with a modified background, the `color.selection.text`
variable must now be set to `CellForeground` instead of omitting it
- URLs are no longer highlighted without a clearly delimited scheme
+- Renamed `visual_bell` to `bell`
### Fixed
diff --git a/Cargo.lock b/Cargo.lock
index 1fa52324..3acfb73b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -32,6 +32,7 @@ dependencies = [
"gl_generator 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
"glutin 0.24.1 (registry+https://github.com/rust-lang/crates.io-index)",
"image 0.23.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.72 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"notify 4.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
diff --git a/alacritty.yml b/alacritty.yml
index ed6feafc..5a14a417 100644
--- a/alacritty.yml
+++ b/alacritty.yml
@@ -265,31 +265,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 rung every time the BEL control character 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`, no command will be executed.
+ #
+ # Example:
+ # command:
+ # program: notify-send
+ # args: ["Hello, World!"]
+ #
+ #command: None
# Background opacity
#
@@ -358,7 +373,7 @@
#
# Alacritty defaults to using the newer ConPTY backend if it is available,
# since it resolves a lot of bugs and is quite a bit faster. If it is not
-# available, the the WinPTY backend will be used instead.
+# available, the WinPTY backend will be used instead.
#
# Setting this option to `true` makes Alacritty use the legacy WinPTY backend,
# even if the ConPTY backend is available.
diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml
index 6cd63867..9ed2d9ce 100644
--- a/alacritty/Cargo.toml
+++ b/alacritty/Cargo.toml
@@ -23,6 +23,7 @@ parking_lot = "0.10.2"
font = { path = "../font", features = ["force_system_fontconfig"] }
urlocator = "0.1.3"
copypasta = { version = "0.7.0", default-features = false }
+libc = "0.2"
unicode-width = "0.1"
[build-dependencies]
diff --git a/alacritty/src/config/mod.rs b/alacritty/src/config/mod.rs
index f416039c..ffa7cbd3 100644
--- a/alacritty/src/config/mod.rs
+++ b/alacritty/src/config/mod.rs
@@ -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)]
diff --git a/alacritty/src/config/monitor.rs b/alacritty/src/config/monitor.rs
index 42603c7e..2ed0c426 100644
--- a/alacritty/src/config/monitor.rs
+++ b/alacritty/src/config/monitor.rs
@@ -4,7 +4,7 @@ use std::time::Duration;
use notify::{watcher, DebouncedEvent, RecursiveMode, Watcher};
-use alacritty_terminal::util;
+use alacritty_terminal::thread;
use crate::event::{Event, EventProxy};
@@ -20,7 +20,7 @@ impl Monitor {
let path = path.into();
Monitor {
- _thread: util::thread::spawn_named("config watcher", move || {
+ _thread: thread::spawn_named("config watcher", move || {
let (tx, rx) = mpsc::channel();
// The Duration argument is a debouncing period.
let mut watcher =
diff --git a/alacritty_terminal/src/util.rs b/alacritty/src/daemon.rs
index f996359a..4a6b6f83 100644
--- a/alacritty_terminal/src/util.rs
+++ b/alacritty/src/daemon.rs
@@ -1,34 +1,53 @@
use std::ffi::OsStr;
+use std::fmt::Debug;
use std::io;
-use std::process::{Command, Stdio};
-
#[cfg(not(windows))]
use std::os::unix::process::CommandExt;
-
#[cfg(windows)]
use std::os::windows::process::CommandExt;
+use std::process::{Command, Stdio};
+
+use log::{debug, warn};
+
#[cfg(windows)]
use winapi::um::winbase::{CREATE_NEW_PROCESS_GROUP, CREATE_NO_WINDOW};
-/// Threading utilities.
-pub mod thread {
- /// Like `thread::spawn`, but with a `name` argument.
- pub fn spawn_named<F, T, S>(name: S, f: F) -> std::thread::JoinHandle<T>
- where
- F: FnOnce() -> T + Send + 'static,
- T: Send + 'static,
- S: Into<String>,
- {
- std::thread::Builder::new().name(name.into()).spawn(f).expect("thread spawn works")
+/// Start the daemon and log error on failure.
+pub fn start_daemon<I, S>(program: &str, args: I)
+where
+ I: IntoIterator<Item = S> + Debug + Copy,
+ S: AsRef<OsStr>,
+{
+ match spawn_daemon(program, args) {
+ Ok(_) => debug!("Launched {} with args {:?}", program, args),
+ Err(_) => warn!("Unable to launch {} with args {:?}", program, args),
}
+}
- pub use std::thread::*;
+#[cfg(windows)]
+fn spawn_daemon<I, S>(program: &str, args: I) -> io::Result<()>
+where
+ I: IntoIterator<Item = S> + Copy,
+ S: AsRef<OsStr>,
+{
+ // Setting all the I/O handles to null and setting the
+ // CREATE_NEW_PROCESS_GROUP and CREATE_NO_WINDOW has the effect
+ // that console applications will run without opening a new
+ // console window.
+ Command::new(program)
+ .args(args)
+ .stdin(Stdio::null())
+ .stdout(Stdio::null())
+ .stderr(Stdio::null())
+ .creation_flags(CREATE_NEW_PROCESS_GROUP | CREATE_NO_WINDOW)
+ .spawn()
+ .map(|_| ())
}
#[cfg(not(windows))]
-pub fn start_daemon<I, S>(program: &str, args: I) -> io::Result<()>
+fn spawn_daemon<I, S>(program: &str, args: I) -> io::Result<()>
where
- I: IntoIterator<Item = S>,
+ I: IntoIterator<Item = S> + Copy,
S: AsRef<OsStr>,
{
unsafe {
@@ -38,13 +57,13 @@ where
.stdout(Stdio::null())
.stderr(Stdio::null())
.pre_exec(|| {
- match ::libc::fork() {
+ match libc::fork() {
-1 => return Err(io::Error::last_os_error()),
0 => (),
- _ => ::libc::_exit(0),
+ _ => libc::_exit(0),
}
- if ::libc::setsid() == -1 {
+ if libc::setsid() == -1 {
return Err(io::Error::last_os_error());
}
@@ -55,23 +74,3 @@ where
.map(|_| ())
}
}
-
-#[cfg(windows)]
-pub fn start_daemon<I, S>(program: &str, args: I) -> io::Result<()>
-where
- I: IntoIterator<Item = S>,
- S: AsRef<OsStr>,
-{
- // Setting all the I/O handles to null and setting the
- // CREATE_NEW_PROCESS_GROUP and CREATE_NO_WINDOW has the effect
- // that console applications will run without opening a new
- // console window.
- Command::new(program)
- .args(args)
- .stdin(Stdio::null())
- .stdout(Stdio::null())
- .stderr(Stdio::null())
- .creation_flags(CREATE_NEW_PROCESS_GROUP | CREATE_NO_WINDOW)
- .spawn()
- .map(|_| ())
-}
diff --git a/alacritty/src/display.rs b/alacritty/src/display.rs
index 53e6fc58..0a3bea34 100644
--- a/alacritty/src/display.rs
+++ b/alacritty/src/display.rs
@@ -540,7 +540,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);
diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs
index edbc4086..f264aab5 100644
--- a/alacritty/src/event.rs
+++ b/alacritty/src/event.rs
@@ -3,6 +3,7 @@
use std::borrow::Cow;
use std::cmp::{max, min};
use std::env;
+use std::fmt::Debug;
#[cfg(unix)]
use std::fs;
use std::fs::File;
@@ -20,7 +21,7 @@ use glutin::event_loop::{ControlFlow, EventLoop, EventLoopProxy, EventLoopWindow
use glutin::platform::desktop::EventLoopExtDesktop;
#[cfg(not(any(target_os = "macos", windows)))]
use glutin::platform::unix::EventLoopWindowTargetExtUnix;
-use log::{debug, info, warn};
+use log::info;
use serde_json as json;
#[cfg(target_os = "macos")]
@@ -38,12 +39,12 @@ use alacritty_terminal::term::cell::Cell;
use alacritty_terminal::term::{ClipboardType, SizeInfo, Term, TermMode};
#[cfg(not(windows))]
use alacritty_terminal::tty;
-use alacritty_terminal::util::start_daemon;
use crate::cli::Options;
use crate::clipboard::Clipboard;
use crate::config;
use crate::config::Config;
+use crate::daemon::start_daemon;
use crate::display::{Display, DisplayUpdate};
use crate::input::{self, ActionContext as _, FONT_SIZE_STEP};
use crate::scheduler::{Scheduler, TimerId};
@@ -290,10 +291,7 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext<T> for ActionCon
#[cfg(not(unix))]
let args: Vec<String> = Vec::new();
- match start_daemon(&alacritty, &args) {
- Ok(_) => debug!("Started new Alacritty process: {} {:?}", alacritty, args),
- Err(_) => warn!("Unable to start new Alacritty process: {} {:?}", alacritty, args),
- }
+ start_daemon(&alacritty, &args);
}
/// Spawn URL launcher when clicking on URLs.
@@ -308,10 +306,7 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext<T> for ActionCon
let end = self.terminal.visible_to_buffer(url.end());
args.push(self.terminal.bounds_to_string(start, end));
- match start_daemon(launcher.program(), &args) {
- Ok(_) => debug!("Launched {} with args {:?}", launcher.program(), args),
- Err(_) => warn!("Unable to launch {} with args {:?}", launcher.program(), args),
- }
+ start_daemon(launcher.program(), &args);
}
}
@@ -839,8 +834,10 @@ impl<N: Notify + OnResize> Processor<N> {
Event::TerminalEvent(event) => match event {
TerminalEvent::Title(title) => processor.ctx.window.set_title(&title),
TerminalEvent::Wakeup => processor.ctx.terminal.dirty = true,
- TerminalEvent::Urgent => {
- processor.ctx.window.set_urgent(!processor.ctx.terminal.is_focused)
+ TerminalEvent::Bell => {
+ let bell_command = processor.ctx.config.bell().command.as_ref();
+ let _ = bell_command.map(|cmd| start_daemon(cmd.program(), cmd.args()));
+ processor.ctx.window.set_urgent(!processor.ctx.terminal.is_focused);
},
TerminalEvent::ClipboardStore(clipboard_type, content) => {
processor.ctx.clipboard.store(clipboard_type, content);
diff --git a/alacritty/src/input.rs b/alacritty/src/input.rs
index 48450b12..cab0f0e2 100644
--- a/alacritty/src/input.rs
+++ b/alacritty/src/input.rs
@@ -10,7 +10,7 @@ use std::cmp::{max, min, Ordering};
use std::marker::PhantomData;
use std::time::{Duration, Instant};
-use log::{debug, trace, warn};
+use log::trace;
use glutin::dpi::PhysicalPosition;
use glutin::event::{
@@ -30,11 +30,11 @@ use alacritty_terminal::message_bar::{self, Message};
use alacritty_terminal::selection::SelectionType;
use alacritty_terminal::term::mode::TermMode;
use alacritty_terminal::term::{ClipboardType, SizeInfo, Term};
-use alacritty_terminal::util::start_daemon;
use alacritty_terminal::vi_mode::ViMotion;
use crate::clipboard::Clipboard;
use crate::config::{Action, Binding, Config, Key, ViAction};
+use crate::daemon::start_daemon;
use crate::event::{ClickState, Event, Mouse, TYPING_SEARCH_DELAY};
use crate::scheduler::{Scheduler, TimerId};
use crate::url::{Url, Urls};
@@ -160,10 +160,7 @@ impl<T: EventListener> Execute<T> for Action {
let program = program.program();
trace!("Running command {} with args {:?}", program, args);
- match start_daemon(program, args) {
- Ok(_) => debug!("Spawned new proc"),
- Err(err) => warn!("Couldn't run command {}", err),
- }
+ start_daemon(program, args);
},
Action::ClearSelection => ctx.clear_selection(),
Action::ToggleViMode => ctx.terminal_mut().toggle_vi_mode(),
diff --git a/alacritty/src/main.rs b/alacritty/src/main.rs
index ab4acaa7..9fbcab55 100644
--- a/alacritty/src/main.rs
+++ b/alacritty/src/main.rs
@@ -36,6 +36,7 @@ mod cli;
mod clipboard;
mod config;
mod cursor;
+mod daemon;
mod display;
mod event;
mod input;
diff --git a/alacritty/src/renderer/mod.rs b/alacritty/src/renderer/mod.rs
index 7dc037a1..bd9f4ae7 100644
--- a/alacritty/src/renderer/mod.rs
+++ b/alacritty/src/renderer/mod.rs
@@ -24,7 +24,7 @@ use alacritty_terminal::index::{Column, Line};
use alacritty_terminal::term::cell::{self, Flags};
use alacritty_terminal::term::color::Rgb;
use alacritty_terminal::term::{self, CursorKey, RenderableCell, RenderableCellContent, SizeInfo};
-use alacritty_terminal::util;
+use alacritty_terminal::thread;
use std::fmt::{self, Display, Formatter};
pub mod rects;
@@ -660,7 +660,7 @@ impl QuadRenderer {
let (msg_tx, msg_rx) = mpsc::channel();
if cfg!(feature = "live-shader-reload") {
- util::thread::spawn_named("live shader reload", move || {
+ thread::spawn_named("live shader reload", move || {
let (tx, rx) = std::sync::mpsc::channel();
// The Duration argument is a debouncing period.
let mut watcher =
diff --git a/alacritty_terminal/src/config/bell.rs b/alacritty_terminal/src/config/bell.rs
new file mode 100644
index 00000000..97010f31
--- /dev/null
+++ b/alacritty_terminal/src/config/bell.rs
@@ -0,0 +1,120 @@
+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,
+
+ /// Visual bell flash color.
+ #[serde(deserialize_with = "deserialize_bell_color")]
+ pub color: Rgb,
+
+ /// Command to run on bell.
+ #[serde(deserialize_with = "deserialize_bell_command")]
+ pub command: Option<Program>,
+}
+
+impl Default for BellConfig {
+ fn default() -> Self {
+ Self {
+ animation: Default::default(),
+ duration: Default::default(),
+ command: Default::default(),
+ color: DEFAULT_BELL_COLOR,
+ }
+ }
+}
+
+impl BellConfig {
+ /// Visual bell duration in milliseconds.
+ #[inline]
+ pub fn duration(&self) -> Duration {
+ Duration::from_millis(u64::from(self.duration))
+ }
+}
+
+fn deserialize_bell_color<'a, D>(deserializer: D) -> Result<Rgb, D::Error>
+where
+ D: Deserializer<'a>,
+{
+ let value = Value::deserialize(deserializer)?;
+ match Rgb::deserialize(value) {
+ Ok(value) => Ok(value),
+ Err(err) => {
+ error!(
+ target: LOG_TARGET_CONFIG,
+ "Problem with config: {}, using default color value {}", err, DEFAULT_BELL_COLOR
+ );
+
+ Ok(DEFAULT_BELL_COLOR)
+ },
+ }
+}
+
+fn deserialize_bell_command<'a, D>(deserializer: D) -> 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 Program::deserialize(val) {
+ Ok(command) => Ok(Some(command)),
+ Err(err) => {
+ error!(target: LOG_TARGET_CONFIG, "Problem with config: {}; ignoring field", 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
+ }
+}
diff --git a/alacritty_terminal/src/config/mod.rs b/alacritty_terminal/src/config/mod.rs
index e3d72fda..83dcd7b8 100644
--- a/alacritty_terminal/src/config/mod.rs
+++ b/alacritty_terminal/src/config/mod.rs
@@ -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;
+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};
pub const LOG_TARGET_CONFIG: &str = "alacritty_config";
@@ -69,9 +69,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")]
@@ -114,6 +114,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>,
@@ -176,6 +180,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)]
diff --git a/alacritty_terminal/src/config/visual_bell.rs b/alacritty_terminal/src/config/visual_bell.rs
deleted file mode 100644
index 1a0a327b..00000000
--- a/alacritty_terminal/src/config/visual_bell.rs
+++ /dev/null
@@ -1,76 +0,0 @@
-use std::time::Duration;
-
-use serde::Deserialize;
-
-use crate::config::failure_default;
-use crate::term::color::Rgb;
-
-#[serde(default)]
-#[derive(Deserialize, Clone, Debug, PartialEq, Eq)]
-pub struct VisualBellConfig {
- /// 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,
-
- /// Visual bell flash color.
- #[serde(deserialize_with = "failure_default")]
- pub color: Rgb,
-}
-
-impl Default for VisualBellConfig {
- fn default() -> VisualBellConfig {
- VisualBellConfig {
- animation: Default::default(),
- duration: Default::default(),
- color: default_visual_bell_color(),
- }
- }
-}
-
-impl VisualBellConfig {
- /// Visual bell duration in milliseconds.
- #[inline]
- pub fn duration(&self) -> Duration {
- Duration::from_millis(u64::from(self.duration))
- }
-}
-
-/// `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 {
- // 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 VisualBellAnimation {
- fn default() -> Self {
- VisualBellAnimation::EaseOutExpo
- }
-}
-
-fn default_visual_bell_color() -> Rgb {
- Rgb { r: 255, g: 255, b: 255 }
-}
diff --git a/alacritty_terminal/src/event.rs b/alacritty_terminal/src/event.rs
index 296e3bb0..863a2fbf 100644
--- a/alacritty_terminal/src/event.rs
+++ b/alacritty_terminal/src/event.rs
@@ -11,7 +11,7 @@ pub enum Event {
ClipboardStore(ClipboardType, String),
ClipboardLoad(ClipboardType, Arc<dyn Fn(&str) -> String + Sync + Send + 'static>),
Wakeup,
- Urgent,
+ Bell,
Exit,
}
@@ -23,7 +23,7 @@ impl Debug for Event {
Event::ClipboardStore(ty, text) => write!(f, "ClipboardStore({:?}, {})", ty, text),
Event::ClipboardLoad(ty, _) => write!(f, "ClipboardLoad({:?})", ty),
Event::Wakeup => write!(f, "Wakeup"),
- Event::Urgent => write!(f, "Urgent"),
+ Event::Bell => write!(f, "Bell"),
Event::Exit => write!(f, "Exit"),
}
}
diff --git a/alacritty_terminal/src/event_loop.rs b/alacritty_terminal/src/event_loop.rs
index 46216605..156510b0 100644
--- a/alacritty_terminal/src/event_loop.rs
+++ b/alacritty_terminal/src/event_loop.rs
@@ -6,6 +6,7 @@ use std::fs::File;
use std::io::{self, ErrorKind, Read, Write};
use std::marker::Send;
use std::sync::Arc;
+use std::thread::JoinHandle;
use log::error;
#[cfg(not(windows))]
@@ -18,8 +19,8 @@ use crate::config::Config;
use crate::event::{self, Event, EventListener};
use crate::sync::FairMutex;
use crate::term::{SizeInfo, Term};
+use crate::thread;
use crate::tty;
-use crate::util::thread;
/// Max bytes to read from the PTY.
const MAX_READ: usize = 0x10_000;
@@ -300,7 +301,7 @@ where
Ok(())
}
- pub fn spawn(mut self) -> thread::JoinHandle<(Self, State)> {
+ pub fn spawn(mut self) -> JoinHandle<(Self, State)> {
thread::spawn_named("PTY reader", move || {
let mut state = State::default();
let mut buf = [0u8; MAX_READ];
diff --git a/alacritty_terminal/src/lib.rs b/alacritty_terminal/src/lib.rs
index 1d2fe551..7130218b 100644
--- a/alacritty_terminal/src/lib.rs
+++ b/alacritty_terminal/src/lib.rs
@@ -22,8 +22,8 @@ pub mod panic;
pub mod selection;
pub mod sync;
pub mod term;
+pub mod thread;
pub mod tty;
-pub mod util;
pub mod vi_mode;
pub use crate::grid::Grid;
diff --git a/alacritty_terminal/src/term/color.rs b/alacritty_terminal/src/term/color.rs
index f20601d6..9aeb7061 100644
--- a/alacritty_terminal/src/term/color.rs
+++ b/alacritty_terminal/src/term/color.rs
@@ -1,4 +1,4 @@
-use std::fmt;
+use std::fmt::{self, Display, Formatter};
use std::ops::{Index, IndexMut, Mul};
use std::str::FromStr;
@@ -64,7 +64,7 @@ impl<'de> Deserialize<'de> for Rgb {
impl<'a> Visitor<'a> for RgbVisitor {
type Value = Rgb;
- fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.write_str("hex color like #ff00ff")
}
@@ -94,6 +94,12 @@ impl<'de> Deserialize<'de> for Rgb {
}
}
+impl Display for Rgb {
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ write!(f, "#{:02x}{:02x}{:02x}", self.r, self.g, self.b)
+ }
+}
+
impl FromStr for Rgb {
type Err = ();
diff --git a/alacritty_terminal/src/term/mod.rs b/alacritty_terminal/src/term/mod.rs
index d59838d4..f3f22d47 100644
--- a/alacritty_terminal/src/term/mod.rs
+++ b/alacritty_terminal/src/term/mod.rs
@@ -14,7 +14,7 @@ use unicode_width::UnicodeWidthChar;
use crate::ansi::{
self, Attr, CharsetIndex, Color, CursorStyle, Handler, NamedColor, StandardCharset,
};
-use crate::config::{Config, VisualBellAnimation};
+use crate::config::{BellAnimation, BellConfig, Config};
use crate::event::{Event, EventListener};
use crate::grid::{Dimensions, DisplayIter, Grid, IndexRegion, Indexed, Scroll};
use crate::index::{self, Boundary, Column, Direction, IndexRange, Line, Point, Side};
@@ -467,7 +467,7 @@ pub use crate::term::mode::TermMode;
pub struct VisualBell {
/// Visual bell animation.
- animation: VisualBellAnimation,
+ animation: BellAnimation,
/// Visual bell duration.
duration: Duration,
@@ -484,15 +484,6 @@ fn cubic_bezier(p0: f64, p1: f64, p2: f64, p3: f64, x: f64) -> f64 {
}
impl VisualBell {
- pub fn new<C>(config: &Config<C>) -> VisualBell {
- let visual_bell_config = &config.visual_bell;
- VisualBell {
- animation: visual_bell_config.animation,
- duration: visual_bell_config.duration(),
- start_time: None,
- }
- }
-
/// Ring the visual bell, and return its intensity.
pub fn ring(&mut self) -> f64 {
let now = Instant::now();
@@ -557,19 +548,17 @@ impl VisualBell {
// VisualBell. When `time` is 0.0, `inverse_intensity` is 0.0,
// and when `time` is 1.0, `inverse_intensity` is 1.0.
let inverse_intensity = match self.animation {
- VisualBellAnimation::Ease | VisualBellAnimation::EaseOut => {
+ BellAnimation::Ease | BellAnimation::EaseOut => {
cubic_bezier(0.25, 0.1, 0.25, 1.0, time)
},
- VisualBellAnimation::EaseOutSine => cubic_bezier(0.39, 0.575, 0.565, 1.0, time),
- VisualBellAnimation::EaseOutQuad => cubic_bezier(0.25, 0.46, 0.45, 0.94, time),
- VisualBellAnimation::EaseOutCubic => {
- cubic_bezier(0.215, 0.61, 0.355, 1.0, time)
- },
- VisualBellAnimation::EaseOutQuart => cubic_bezier(0.165, 0.84, 0.44, 1.0, time),
- VisualBellAnimation::EaseOutQuint => cubic_bezier(0.23, 1.0, 0.32, 1.0, time),
- VisualBellAnimation::EaseOutExpo => cubic_bezier(0.19, 1.0, 0.22, 1.0, time),
- VisualBellAnimation::EaseOutCirc => cubic_bezier(0.075, 0.82, 0.165, 1.0, time),
- VisualBellAnimation::Linear => time,
+ BellAnimation::EaseOutSine => cubic_bezier(0.39, 0.575, 0.565, 1.0, time),
+ BellAnimation::EaseOutQuad => cubic_bezier(0.25, 0.46, 0.45, 0.94, time),
+ BellAnimation::EaseOutCubic => cubic_bezier(0.215, 0.61, 0.355, 1.0, time),
+ BellAnimation::EaseOutQuart => cubic_bezier(0.165, 0.84, 0.44, 1.0, time),
+ BellAnimation::EaseOutQuint => cubic_bezier(0.23, 1.0, 0.32, 1.0, time),
+ BellAnimation::EaseOutExpo => cubic_bezier(0.19, 1.0, 0.22, 1.0, time),
+ BellAnimation::EaseOutCirc => cubic_bezier(0.075, 0.82, 0.165, 1.0, time),
+ BellAnimation::Linear => time,
};
// Since we want the `intensity` of the VisualBell to decay over
@@ -580,9 +569,19 @@ impl VisualBell {
}
pub fn update_config<C>(&mut self, config: &Config<C>) {
- let visual_bell_config = &config.visual_bell;
- self.animation = visual_bell_config.animation;
- self.duration = visual_bell_config.duration();
+ let bell_config = config.bell();
+ self.animation = bell_config.animation;
+ self.duration = bell_config.duration();
+ }
+}
+
+impl From<&BellConfig> for VisualBell {
+ fn from(bell_config: &BellConfig) -> VisualBell {
+ VisualBell {
+ animation: bell_config.animation,
+ duration: bell_config.duration(),
+ start_time: None,
+ }
}
}
@@ -763,7 +762,7 @@ impl<T> Term<T> {
Term {
dirty: false,
- visual_bell: VisualBell::new(config),
+ visual_bell: config.bell().into(),
grid,
inactive_grid: alt,
active_charset: Default::default(),
@@ -1617,7 +1616,7 @@ impl<T: EventListener> Handler for Term<T> {
fn bell(&mut self) {
trace!("Bell");
self.visual_bell.ring();
- self.event_proxy.send_event(Event::Urgent);
+ self.event_proxy.send_event(Event::Bell);
}
#[inline]
diff --git a/alacritty_terminal/src/thread.rs b/alacritty_terminal/src/thread.rs
new file mode 100644
index 00000000..6a93b78d
--- /dev/null
+++ b/alacritty_terminal/src/thread.rs
@@ -0,0 +1,11 @@
+use std::thread::{Builder, JoinHandle};
+
+/// Like `thread::spawn`, but with a `name` argument.
+pub fn spawn_named<F, T, S>(name: S, f: F) -> JoinHandle<T>
+where
+ F: FnOnce() -> T + Send + 'static,
+ T: Send + 'static,
+ S: Into<String>,
+{
+ Builder::new().name(name.into()).spawn(f).expect("thread spawn works")
+}