diff options
author | Christian Duerr <contact@christianduerr.com> | 2019-10-05 02:29:26 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-10-05 02:29:26 +0200 |
commit | 729eef0c933831bccfeac6a355bdb410787fbe5f (patch) | |
tree | 35cdf2e6427ad18bc53efbab4cab34a0af2054d7 /alacritty_terminal/src/config | |
parent | b0c6fdff763f7271506d26d7e768e6377fdc691b (diff) | |
download | alacritty-729eef0c933831bccfeac6a355bdb410787fbe5f.tar.gz alacritty-729eef0c933831bccfeac6a355bdb410787fbe5f.zip |
Update to winit/glutin EventLoop 2.0
This takes the latest glutin master to port Alacritty to the EventLoop
2.0 rework.
This changes a big part of the event loop handling by pushing the event
loop in a separate thread from the renderer and running both in
parallel.
Fixes #2796.
Fixes #2694.
Fixes #2643.
Fixes #2625.
Fixes #2618.
Fixes #2601.
Fixes #2564.
Fixes #2456.
Fixes #2438.
Fixes #2334.
Fixes #2254.
Fixes #2217.
Fixes #1789.
Fixes #1750.
Fixes #1125.
Diffstat (limited to 'alacritty_terminal/src/config')
-rw-r--r-- | alacritty_terminal/src/config/bindings.rs | 1023 | ||||
-rw-r--r-- | alacritty_terminal/src/config/colors.rs | 18 | ||||
-rw-r--r-- | alacritty_terminal/src/config/debug.rs | 11 | ||||
-rw-r--r-- | alacritty_terminal/src/config/font.rs | 10 | ||||
-rw-r--r-- | alacritty_terminal/src/config/mod.rs | 86 | ||||
-rw-r--r-- | alacritty_terminal/src/config/monitor.rs | 79 | ||||
-rw-r--r-- | alacritty_terminal/src/config/mouse.rs | 108 | ||||
-rw-r--r-- | alacritty_terminal/src/config/scrolling.rs | 12 | ||||
-rw-r--r-- | alacritty_terminal/src/config/test.rs | 22 | ||||
-rw-r--r-- | alacritty_terminal/src/config/visual_bell.rs | 4 | ||||
-rw-r--r-- | alacritty_terminal/src/config/window.rs | 6 |
11 files changed, 58 insertions, 1321 deletions
diff --git a/alacritty_terminal/src/config/bindings.rs b/alacritty_terminal/src/config/bindings.rs deleted file mode 100644 index 00090bbf..00000000 --- a/alacritty_terminal/src/config/bindings.rs +++ /dev/null @@ -1,1023 +0,0 @@ -// Copyright 2016 Joe Wilm, The Alacritty Project Contributors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use std::fmt; -use std::str::FromStr; - -use glutin::{ModifiersState, MouseButton}; -use serde::de::Error as SerdeError; -use serde::de::{self, MapAccess, Unexpected, Visitor}; -use serde::{Deserialize, Deserializer}; - -use crate::input::{Action, Binding, KeyBinding, MouseBinding}; -use crate::term::TermMode; - -macro_rules! bindings { - ( - $ty:ident; - $( - $key:path - $(,[$($mod:ident: $enabled:expr),*])* - $(,+$mode:expr)* - $(,~$notmode:expr)* - ;$action:expr - );* - $(;)* - ) => {{ - let mut v = Vec::new(); - - $( - let mut _mods = ModifiersState { - $($($mod: $enabled),*,)* - ..Default::default() - }; - let mut _mode = TermMode::empty(); - $(_mode = $mode;)* - let mut _notmode = TermMode::empty(); - $(_notmode = $notmode;)* - - v.push($ty { - trigger: $key, - mods: _mods, - mode: _mode, - notmode: _notmode, - action: $action, - }); - )* - - v - }} -} - -pub fn default_mouse_bindings() -> Vec<MouseBinding> { - bindings!( - MouseBinding; - MouseButton::Middle; Action::PasteSelection; - ) -} - -pub fn default_key_bindings() -> Vec<KeyBinding> { - let mut bindings = bindings!( - KeyBinding; - Key::Paste; Action::Paste; - Key::Copy; Action::Copy; - Key::L, [ctrl: true]; Action::ClearLogNotice; - Key::L, [ctrl: true]; Action::Esc("\x0c".into()); - Key::PageUp, [shift: true], ~TermMode::ALT_SCREEN; Action::ScrollPageUp; - Key::PageDown, [shift: true], ~TermMode::ALT_SCREEN; Action::ScrollPageDown; - Key::Home, [shift: true], ~TermMode::ALT_SCREEN; Action::ScrollToTop; - Key::End, [shift: true], ~TermMode::ALT_SCREEN; Action::ScrollToBottom; - Key::Home, +TermMode::APP_CURSOR; Action::Esc("\x1bOH".into()); - Key::Home, ~TermMode::APP_CURSOR; Action::Esc("\x1b[H".into()); - Key::Home, [shift: true], +TermMode::ALT_SCREEN; Action::Esc("\x1b[1;2H".into()); - Key::End, +TermMode::APP_CURSOR; Action::Esc("\x1bOF".into()); - Key::End, ~TermMode::APP_CURSOR; Action::Esc("\x1b[F".into()); - Key::End, [shift: true], +TermMode::ALT_SCREEN; Action::Esc("\x1b[1;2F".into()); - Key::PageUp; Action::Esc("\x1b[5~".into()); - Key::PageUp, [shift: true], +TermMode::ALT_SCREEN; Action::Esc("\x1b[5;2~".into()); - Key::PageDown; Action::Esc("\x1b[6~".into()); - Key::PageDown, [shift: true], +TermMode::ALT_SCREEN; Action::Esc("\x1b[6;2~".into()); - Key::Tab, [shift: true]; Action::Esc("\x1b[Z".into()); - Key::Back; Action::Esc("\x7f".into()); - Key::Back, [alt: true]; Action::Esc("\x1b\x7f".into()); - Key::Insert; Action::Esc("\x1b[2~".into()); - Key::Delete; Action::Esc("\x1b[3~".into()); - Key::Up, +TermMode::APP_CURSOR; Action::Esc("\x1bOA".into()); - Key::Up, ~TermMode::APP_CURSOR; Action::Esc("\x1b[A".into()); - Key::Down, +TermMode::APP_CURSOR; Action::Esc("\x1bOB".into()); - Key::Down, ~TermMode::APP_CURSOR; Action::Esc("\x1b[B".into()); - Key::Right, +TermMode::APP_CURSOR; Action::Esc("\x1bOC".into()); - Key::Right, ~TermMode::APP_CURSOR; Action::Esc("\x1b[C".into()); - Key::Left, +TermMode::APP_CURSOR; Action::Esc("\x1bOD".into()); - Key::Left, ~TermMode::APP_CURSOR; Action::Esc("\x1b[D".into()); - Key::F1; Action::Esc("\x1bOP".into()); - Key::F2; Action::Esc("\x1bOQ".into()); - Key::F3; Action::Esc("\x1bOR".into()); - Key::F4; Action::Esc("\x1bOS".into()); - Key::F5; Action::Esc("\x1b[15~".into()); - Key::F6; Action::Esc("\x1b[17~".into()); - Key::F7; Action::Esc("\x1b[18~".into()); - Key::F8; Action::Esc("\x1b[19~".into()); - Key::F9; Action::Esc("\x1b[20~".into()); - Key::F10; Action::Esc("\x1b[21~".into()); - Key::F11; Action::Esc("\x1b[23~".into()); - Key::F12; Action::Esc("\x1b[24~".into()); - Key::F13; Action::Esc("\x1b[25~".into()); - Key::F14; Action::Esc("\x1b[26~".into()); - Key::F15; Action::Esc("\x1b[28~".into()); - Key::F16; Action::Esc("\x1b[29~".into()); - Key::F17; Action::Esc("\x1b[31~".into()); - Key::F18; Action::Esc("\x1b[32~".into()); - Key::F19; Action::Esc("\x1b[33~".into()); - Key::F20; Action::Esc("\x1b[34~".into()); - Key::NumpadEnter; Action::Esc("\n".into()); - ); - - // Code Modifiers - // ---------+--------------------------- - // 2 | Shift - // 3 | Alt - // 4 | Shift + Alt - // 5 | Control - // 6 | Shift + Control - // 7 | Alt + Control - // 8 | Shift + Alt + Control - // ---------+--------------------------- - // - // from: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-PC-Style-Function-Keys - let modifiers = vec![ - ModifiersState { shift: true, ..ModifiersState::default() }, - ModifiersState { alt: true, ..ModifiersState::default() }, - ModifiersState { shift: true, alt: true, ..ModifiersState::default() }, - ModifiersState { ctrl: true, ..ModifiersState::default() }, - ModifiersState { shift: true, ctrl: true, ..ModifiersState::default() }, - ModifiersState { alt: true, ctrl: true, ..ModifiersState::default() }, - ModifiersState { shift: true, alt: true, ctrl: true, ..ModifiersState::default() }, - ]; - - for (index, mods) in modifiers.iter().enumerate() { - let modifiers_code = index + 2; - bindings.extend(bindings!( - KeyBinding; - Key::Up, [shift: mods.shift, alt: mods.alt, ctrl: mods.ctrl]; - Action::Esc(format!("\x1b[1;{}A", modifiers_code)); - Key::Down, [shift: mods.shift, alt: mods.alt, ctrl: mods.ctrl]; - Action::Esc(format!("\x1b[1;{}B", modifiers_code)); - Key::Right, [shift: mods.shift, alt: mods.alt, ctrl: mods.ctrl]; - Action::Esc(format!("\x1b[1;{}C", modifiers_code)); - Key::Left, [shift: mods.shift, alt: mods.alt, ctrl: mods.ctrl]; - Action::Esc(format!("\x1b[1;{}D", modifiers_code)); - Key::F1, [shift: mods.shift, alt: mods.alt, ctrl: mods.ctrl]; - Action::Esc(format!("\x1b[1;{}P", modifiers_code)); - Key::F2, [shift: mods.shift, alt: mods.alt, ctrl: mods.ctrl]; - Action::Esc(format!("\x1b[1;{}Q", modifiers_code)); - Key::F3, [shift: mods.shift, alt: mods.alt, ctrl: mods.ctrl]; - Action::Esc(format!("\x1b[1;{}R", modifiers_code)); - Key::F4, [shift: mods.shift, alt: mods.alt, ctrl: mods.ctrl]; - Action::Esc(format!("\x1b[1;{}S", modifiers_code)); - Key::F5, [shift: mods.shift, alt: mods.alt, ctrl: mods.ctrl]; - Action::Esc(format!("\x1b[15;{}~", modifiers_code)); - Key::F6, [shift: mods.shift, alt: mods.alt, ctrl: mods.ctrl]; - Action::Esc(format!("\x1b[17;{}~", modifiers_code)); - Key::F7, [shift: mods.shift, alt: mods.alt, ctrl: mods.ctrl]; - Action::Esc(format!("\x1b[18;{}~", modifiers_code)); - Key::F8, [shift: mods.shift, alt: mods.alt, ctrl: mods.ctrl]; - Action::Esc(format!("\x1b[19;{}~", modifiers_code)); - Key::F9, [shift: mods.shift, alt: mods.alt, ctrl: mods.ctrl]; - Action::Esc(format!("\x1b[20;{}~", modifiers_code)); - Key::F10, [shift: mods.shift, alt: mods.alt, ctrl: mods.ctrl]; - Action::Esc(format!("\x1b[21;{}~", modifiers_code)); - Key::F11, [shift: mods.shift, alt: mods.alt, ctrl: mods.ctrl]; - Action::Esc(format!("\x1b[23;{}~", modifiers_code)); - Key::F12, [shift: mods.shift, alt: mods.alt, ctrl: mods.ctrl]; - Action::Esc(format!("\x1b[24;{}~", modifiers_code)); - Key::F13, [shift: mods.shift, alt: mods.alt, ctrl: mods.ctrl]; - Action::Esc(format!("\x1b[25;{}~", modifiers_code)); - Key::F14, [shift: mods.shift, alt: mods.alt, ctrl: mods.ctrl]; - Action::Esc(format!("\x1b[26;{}~", modifiers_code)); - Key::F15, [shift: mods.shift, alt: mods.alt, ctrl: mods.ctrl]; - Action::Esc(format!("\x1b[28;{}~", modifiers_code)); - Key::F16, [shift: mods.shift, alt: mods.alt, ctrl: mods.ctrl]; - Action::Esc(format!("\x1b[29;{}~", modifiers_code)); - Key::F17, [shift: mods.shift, alt: mods.alt, ctrl: mods.ctrl]; - Action::Esc(format!("\x1b[31;{}~", modifiers_code)); - Key::F18, [shift: mods.shift, alt: mods.alt, ctrl: mods.ctrl]; - Action::Esc(format!("\x1b[32;{}~", modifiers_code)); - Key::F19, [shift: mods.shift, alt: mods.alt, ctrl: mods.ctrl]; - Action::Esc(format!("\x1b[33;{}~", modifiers_code)); - Key::F20, [shift: mods.shift, alt: mods.alt, ctrl: mods.ctrl]; - Action::Esc(format!("\x1b[34;{}~", modifiers_code)); - )); - - // We're adding the following bindings with `Shift` manually above, so skipping them here - // modifiers_code != Shift - if modifiers_code != 2 { - bindings.extend(bindings!( - KeyBinding; - Key::PageUp, [shift: mods.shift, alt: mods.alt, ctrl: mods.ctrl]; - Action::Esc(format!("\x1b[5;{}~", modifiers_code)); - Key::PageDown, [shift: mods.shift, alt: mods.alt, ctrl: mods.ctrl]; - Action::Esc(format!("\x1b[6;{}~", modifiers_code)); - Key::End, [shift: mods.shift, alt: mods.alt, ctrl: mods.ctrl]; - Action::Esc(format!("\x1b[1;{}F", modifiers_code)); - Key::Home, [shift: mods.shift, alt: mods.alt, ctrl: mods.ctrl]; - Action::Esc(format!("\x1b[1;{}H", modifiers_code)); - )); - } - } - - bindings.extend(platform_key_bindings()); - - bindings -} - -#[cfg(not(any(target_os = "macos", test)))] -fn common_keybindings() -> Vec<KeyBinding> { - bindings!( - KeyBinding; - Key::V, [ctrl: true, shift: true]; Action::Paste; - Key::C, [ctrl: true, shift: true]; Action::Copy; - Key::Insert, [shift: true]; Action::PasteSelection; - Key::Key0, [ctrl: true]; Action::ResetFontSize; - Key::Equals, [ctrl: true]; Action::IncreaseFontSize; - Key::Add, [ctrl: true]; Action::IncreaseFontSize; - Key::Subtract, [ctrl: true]; Action::DecreaseFontSize; - Key::Minus, [ctrl: true]; Action::DecreaseFontSize; - ) -} - -#[cfg(not(any(target_os = "macos", target_os = "windows", test)))] -pub fn platform_key_bindings() -> Vec<KeyBinding> { - common_keybindings() -} - -#[cfg(all(target_os = "windows", not(test)))] -pub fn platform_key_bindings() -> Vec<KeyBinding> { - let mut bindings = bindings!( - KeyBinding; - Key::Return, [alt: true]; Action::ToggleFullscreen; - ); - bindings.extend(common_keybindings()); - bindings -} - -#[cfg(all(target_os = "macos", not(test)))] -pub fn platform_key_bindings() -> Vec<KeyBinding> { - bindings!( - KeyBinding; - Key::Key0, [logo: true]; Action::ResetFontSize; - Key::Equals, [logo: true]; Action::IncreaseFontSize; - Key::Add, [logo: true]; Action::IncreaseFontSize; - Key::Minus, [logo: true]; Action::DecreaseFontSize; - Key::F, [ctrl: true, logo: true]; Action::ToggleFullscreen; - Key::K, [logo: true]; Action::ClearHistory; - Key::K, [logo: true]; Action::Esc("\x0c".into()); - Key::V, [logo: true]; Action::Paste; - Key::C, [logo: true]; Action::Copy; - Key::H, [logo: true]; Action::Hide; - Key::Q, [logo: true]; Action::Quit; - Key::W, [logo: true]; Action::Quit; - ) -} - -// Don't return any bindings for tests since they are commented-out by default -#[cfg(test)] -pub fn platform_key_bindings() -> Vec<KeyBinding> { - vec![] -} - -#[derive(Deserialize, Copy, Clone, Debug, Eq, PartialEq, Hash)] -pub enum Key { - Scancode(u32), - Key1, - Key2, - Key3, - Key4, - Key5, - Key6, - Key7, - Key8, - Key9, - Key0, - A, - B, - C, - D, - E, - F, - G, - H, - I, - J, - K, - L, - M, - N, - O, - P, - Q, - R, - S, - T, - U, - V, - W, - X, - Y, - Z, - Escape, - F1, - F2, - F3, - F4, - F5, - F6, - F7, - F8, - F9, - F10, - F11, - F12, - F13, - F14, - F15, - F16, - F17, - F18, - F19, - F20, - F21, - F22, - F23, - F24, - Snapshot, - Scroll, - Pause, - Insert, - Home, - Delete, - End, - PageDown, - PageUp, - Left, - Up, - Right, - Down, - Back, - Return, - Space, - Compose, - Numlock, - Numpad0, - Numpad1, - Numpad2, - Numpad3, - Numpad4, - Numpad5, - Numpad6, - Numpad7, - Numpad8, - Numpad9, - AbntC1, - AbntC2, - Add, - Apostrophe, - Apps, - At, - Ax, - Backslash, - Calculator, - Capital, - Colon, - Comma, - Convert, - Decimal, - Divide, - Equals, - Grave, - Kana, - Kanji, - LAlt, - LBracket, - LControl, - LShift, - LWin, - Mail, - MediaSelect, - MediaStop, - Minus, - Multiply, - Mute, - MyComputer, - NavigateForward, - NavigateBackward, - NextTrack, - NoConvert, - NumpadComma, - NumpadEnter, - NumpadEquals, - OEM102, - Period, - PlayPause, - Power, - PrevTrack, - RAlt, - RBracket, - RControl, - RShift, - RWin, - Semicolon, - Slash, - Sleep, - Stop, - Subtract, - Sysrq, - Tab, - Underline, - Unlabeled, - VolumeDown, - VolumeUp, - Wake, - WebBack, - WebFavorites, - WebForward, - WebHome, - WebRefresh, - WebSearch, - WebStop, - Yen, - Caret, - Copy, - Paste, - Cut, -} - -impl Key { - pub fn from_glutin_input(key: ::glutin::VirtualKeyCode) -> Self { - use glutin::VirtualKeyCode::*; - // Thank you, vim macros and regex! - match key { - Key1 => Key::Key1, - Key2 => Key::Key2, - Key3 => Key::Key3, - Key4 => Key::Key4, - Key5 => Key::Key5, - Key6 => Key::Key6, - Key7 => Key::Key7, - Key8 => Key::Key8, - Key9 => Key::Key9, - Key0 => Key::Key0, - A => Key::A, - B => Key::B, - C => Key::C, - D => Key::D, - E => Key::E, - F => Key::F, - G => Key::G, - H => Key::H, - I => Key::I, - J => Key::J, - K => Key::K, - L => Key::L, - M => Key::M, - N => Key::N, - O => Key::O, - P => Key::P, - Q => Key::Q, - R => Key::R, - S => Key::S, - T => Key::T, - U => Key::U, - V => Key::V, - W => Key::W, - X => Key::X, - Y => Key::Y, - Z => Key::Z, - Escape => Key::Escape, - F1 => Key::F1, - F2 => Key::F2, - F3 => Key::F3, - F4 => Key::F4, - F5 => Key::F5, - F6 => Key::F6, - F7 => Key::F7, - F8 => Key::F8, - F9 => Key::F9, - F10 => Key::F10, - F11 => Key::F11, - F12 => Key::F12, - F13 => Key::F13, - F14 => Key::F14, - F15 => Key::F15, - F16 => Key::F16, - F17 => Key::F17, - F18 => Key::F18, - F19 => Key::F19, - F20 => Key::F20, - F21 => Key::F21, - F22 => Key::F22, - F23 => Key::F23, - F24 => Key::F24, - Snapshot => Key::Snapshot, - Scroll => Key::Scroll, - Pause => Key::Pause, - Insert => Key::Insert, - Home => Key::Home, - Delete => Key::Delete, - End => Key::End, - PageDown => Key::PageDown, - PageUp => Key::PageUp, - Left => Key::Left, - Up => Key::Up, - Right => Key::Right, - Down => Key::Down, - Back => Key::Back, - Return => Key::Return, - Space => Key::Space, - Compose => Key::Compose, - Numlock => Key::Numlock, - Numpad0 => Key::Numpad0, - Numpad1 => Key::Numpad1, - Numpad2 => Key::Numpad2, - Numpad3 => Key::Numpad3, - Numpad4 => Key::Numpad4, - Numpad5 => Key::Numpad5, - Numpad6 => Key::Numpad6, - Numpad7 => Key::Numpad7, - Numpad8 => Key::Numpad8, - Numpad9 => Key::Numpad9, - AbntC1 => Key::AbntC1, - AbntC2 => Key::AbntC2, - Add => Key::Add, - Apostrophe => Key::Apostrophe, - Apps => Key::Apps, - At => Key::At, - Ax => Key::Ax, - Backslash => Key::Backslash, - Calculator => Key::Calculator, - Capital => Key::Capital, - Colon => Key::Colon, - Comma => Key::Comma, - Convert => Key::Convert, - Decimal => Key::Decimal, - Divide => Key::Divide, - Equals => Key::Equals, - Grave => Key::Grave, - Kana => Key::Kana, - Kanji => Key::Kanji, - LAlt => Key::LAlt, - LBracket => Key::LBracket, - LControl => Key::LControl, - LShift => Key::LShift, - LWin => Key::LWin, - Mail => Key::Mail, - MediaSelect => Key::MediaSelect, - MediaStop => Key::MediaStop, - Minus => Key::Minus, - Multiply => Key::Multiply, - Mute => Key::Mute, - MyComputer => Key::MyComputer, - NavigateForward => Key::NavigateForward, - NavigateBackward => Key::NavigateBackward, - NextTrack => Key::NextTrack, - NoConvert => Key::NoConvert, - NumpadComma => Key::NumpadComma, - NumpadEnter => Key::NumpadEnter, - NumpadEquals => Key::NumpadEquals, - OEM102 => Key::OEM102, - Period => Key::Period, - PlayPause => Key::PlayPause, - Power => Key::Power, - PrevTrack => Key::PrevTrack, - RAlt => Key::RAlt, - RBracket => Key::RBracket, - RControl => Key::RControl, - RShift => Key::RShift, - RWin => Key::RWin, - Semicolon => Key::Semicolon, - Slash => Key::Slash, - Sleep => Key::Sleep, - Stop => Key::Stop, - Subtract => Key::Subtract, - Sysrq => Key::Sysrq, - Tab => Key::Tab, - Underline => Key::Underline, - Unlabeled => Key::Unlabeled, - VolumeDown => Key::VolumeDown, - VolumeUp => Key::VolumeUp, - Wake => Key::Wake, - WebBack => Key::WebBack, - WebFavorites => Key::WebFavorites, - WebForward => Key::WebForward, - WebHome => Key::WebHome, - WebRefresh => Key::WebRefresh, - WebSearch => Key::WebSearch, - WebStop => Key::WebStop, - Yen => Key::Yen, - Caret => Key::Caret, - Copy => Key::Copy, - Paste => Key::Paste, - Cut => Key::Cut, - } - } -} - -struct ModeWrapper { - pub mode: TermMode, - pub not_mode: TermMode, -} - -impl<'a> Deserialize<'a> for ModeWrapper { - fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error> - where - D: Deserializer<'a>, - { - struct ModeVisitor; - - impl<'a> Visitor<'a> for ModeVisitor { - type Value = ModeWrapper; - - fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("Combination of AppCursor | AppKeypad, possibly with negation (~)") - } - - fn visit_str<E>(self, value: &str) -> ::std::result::Result<ModeWrapper, E> - where - E: de::Error, - { - let mut res = ModeWrapper { mode: TermMode::empty(), not_mode: TermMode::empty() }; - - for modifier in value.split('|') { - match modifier.trim().to_lowercase().as_str() { - "appcursor" => res.mode |= TermMode::APP_CURSOR, - "~appcursor" => res.not_mode |= TermMode::APP_CURSOR, - "appkeypad" => res.mode |= TermMode::APP_KEYPAD, - "~appkeypad" => res.not_mode |= TermMode::APP_KEYPAD, - "~alt" => res.not_mode |= TermMode::ALT_SCREEN, - "alt" => res.mode |= TermMode::ALT_SCREEN, - _ => error!("Unknown mode {:?}", modifier), - } - } - - Ok(res) - } - } - deserializer.deserialize_str(ModeVisitor) - } -} - -struct MouseButtonWrapper(MouseButton); - -impl MouseButtonWrapper { - fn into_inner(self) -> MouseButton { - self.0 - } -} - -impl<'a> Deserialize<'a> for MouseButtonWrapper { - fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error> - where - D: Deserializer<'a>, - { - struct MouseButtonVisitor; - - impl<'a> Visitor<'a> for MouseButtonVisitor { - type Value = MouseButtonWrapper; - - fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("Left, Right, Middle, or a number") - } - - fn visit_str<E>(self, value: &str) -> ::std::result::Result<MouseButtonWrapper, E> - where - E: de::Error, - { - match value { - "Left" => Ok(MouseButtonWrapper(MouseButton::Left)), - "Right" => Ok(MouseButtonWrapper(MouseButton::Right)), - "Middle" => Ok(MouseButtonWrapper(MouseButton::Middle)), - _ => { - if let Ok(index) = u8::from_str(value) { - Ok(MouseButtonWrapper(MouseButton::Other(index))) - } else { - Err(E::invalid_value(Unexpected::Str(value), &self)) - } - }, - } - } - } - - deserializer.deserialize_str(MouseButtonVisitor) - } -} - -/// Bindings are deserialized into a `RawBinding` before being parsed as a -/// `KeyBinding` or `MouseBinding`. -#[derive(PartialEq, Eq)] -struct RawBinding { - key: Option<Key>, - mouse: Option<MouseButton>, - mods: ModifiersState, - mode: TermMode, - notmode: TermMode, - action: Action, -} - -impl RawBinding { - fn into_mouse_binding(self) -> ::std::result::Result<MouseBinding, Self> { - if let Some(mouse) = self.mouse { - Ok(Binding { - trigger: mouse, - mods: self.mods, - action: self.action, - mode: self.mode, - notmode: self.notmode, - }) - } else { - Err(self) - } - } - - fn into_key_binding(self) -> ::std::result::Result<KeyBinding, Self> { - if let Some(key) = self.key { - Ok(KeyBinding { - trigger: key, - mods: self.mods, - action: self.action, - mode: self.mode, - notmode: self.notmode, - }) - } else { - Err(self) - } - } -} - -impl<'a> Deserialize<'a> for RawBinding { - fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error> - where - D: Deserializer<'a>, - { - enum Field { - Key, - Mods, - Mode, - Action, - Chars, - Mouse, - Command, - } - - impl<'a> Deserialize<'a> for Field { - fn deserialize<D>(deserializer: D) -> ::std::result::Result<Field, D::Error> - where - D: Deserializer<'a>, - { - struct FieldVisitor; - - static FIELDS: &[&str] = - &["key", "mods", "mode", "action", "chars", "mouse", "command"]; - - impl<'a> Visitor<'a> for FieldVisitor { - type Value = Field; - - fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("binding fields") - } - - fn visit_str<E>(self, value: &str) -> ::std::result::Result<Field, E> - where - E: de::Error, - { - match value { - "key" => Ok(Field::Key), - "mods" => Ok(Field::Mods), - "mode" => Ok(Field::Mode), - "action" => Ok(Field::Action), - "chars" => Ok(Field::Chars), - "mouse" => Ok(Field::Mouse), - "command" => Ok(Field::Command), - _ => Err(E::unknown_field(value, FIELDS)), - } - } - } - - deserializer.deserialize_str(FieldVisitor) - } - } - - struct RawBindingVisitor; - impl<'a> Visitor<'a> for RawBindingVisitor { - type Value = RawBinding; - - fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("binding specification") - } - - fn visit_map<V>(self, mut map: V) -> ::std::result::Result<RawBinding, V::Error> - where - V: MapAccess<'a>, - { - let mut mods: Option<ModifiersState> = None; - let mut key: Option<Key> = None; - let mut chars: Option<String> = None; - let mut action: Option<crate::input::Action> = None; - let mut mode: Option<TermMode> = None; - let mut not_mode: Option<TermMode> = None; - let mut mouse: Option<MouseButton> = None; - let mut command: Option<CommandWrapper> = None; - - use ::serde::de::Error; - - while let Some(struct_key) = map.next_key::<Field>()? { - match struct_key { - Field::Key => { - if key.is_some() { - return Err(<V::Error as Error>::duplicate_field("key")); - } - - let val = map.next_value::<serde_yaml::Value>()?; - if val.is_u64() { - let scancode = val.as_u64().unwrap(); - if scancode > u64::from(::std::u32::MAX) { - return Err(<V::Error as Error>::custom(format!( - "Invalid key binding, scancode too big: {}", - scancode - ))); - } - key = Some(Key::Scancode(scancode as u32)); - } else { - let k = Key::deserialize(val).map_err(V::Error::custom)?; - key = Some(k); - } - }, - Field::Mods => { - if mods.is_some() { - return Err(<V::Error as Error>::duplicate_field("mods")); - } - - mods = Some(map.next_value::<ModsWrapper>()?.into_inner()); - }, - Field::Mode => { - if mode.is_some() { - return Err(<V::Error as Error>::duplicate_field("mode")); - } - - let mode_deserializer = map.next_value::<ModeWrapper>()?; - mode = Some(mode_deserializer.mode); - not_mode = Some(mode_deserializer.not_mode); - }, - Field::Action => { - if action.is_some() { - return Err(<V::Error as Error>::duplicate_field("action")); - } - - action = Some(map.next_value::<Action>()?); - }, - Field::Chars => { - if chars.is_some() { - return Err(<V::Error as Error>::duplicate_field("chars")); - } - - chars = Some(map.next_value()?); - }, - Field::Mouse => { - if chars.is_some() { - return Err(<V::Error as Error>::duplicate_field("mouse")); - } - - mouse = Some(map.next_value::<MouseButtonWrapper>()?.into_inner()); - }, - Field::Command => { - if command.is_some() { - return Err(<V::Error as Error>::duplicate_field("command")); - } - - command = Some(map.next_value::<CommandWrapper>()?); - }, - } - } - - let action = match (action, chars, command) { - (Some(action), None, None) => action, - (None, Some(chars), None) => Action::Esc(chars), - (None, None, Some(cmd)) => match cmd { - CommandWrapper::Just(program) => Action::Command(program, vec![]), - CommandWrapper::WithArgs { program, args } => { - Action::Command(program, args) - }, - }, - (None, None, None) => { - return Err(V::Error::custom("must specify chars, action or command")); - }, - _ => { - return Err(V::Error::custom("must specify only chars, action or command")) - }, - }; - - let mode = mode.unwrap_or_else(TermMode::empty); - let not_mode = not_mode.unwrap_or_else(TermMode::empty); - let mods = mods.unwrap_or_else(ModifiersState::default); - - if mouse.is_none() && key.is_none() { - return Err(V::Error::custom("bindings require mouse button or key")); - } - - Ok(RawBinding { mode, notmode: not_mode, action, key, mouse, mods }) - } - } - - const FIELDS: &[&str] = &["key", "mods", "mode", "action", "chars", "mouse", "command"]; - - deserializer.deserialize_struct("RawBinding", FIELDS, RawBindingVisitor) - } -} - -impl<'a> Deserialize<'a> for MouseBinding { - fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error> - where - D: Deserializer<'a>, - { - let raw = RawBinding::deserialize(deserializer)?; - raw.into_mouse_binding().map_err(|_| D::Error::custom("expected mouse binding")) - } -} - -impl<'a> Deserialize<'a> for KeyBinding { - fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error> - where - D: Deserializer<'a>, - { - let raw = RawBinding::deserialize(deserializer)?; - raw.into_key_binding().map_err(|_| D::Error::custom("expected key binding")) - } -} - -#[serde(untagged)] -#[derive(Debug, Deserialize, Clone, PartialEq, Eq)] -pub enum CommandWrapper { - Just(String), - WithArgs { - program: String, - #[serde(default)] - args: Vec<String>, - }, -} - -impl CommandWrapper { - pub fn program(&self) -> &str { - match self { - CommandWrapper::Just(program) => program, - CommandWrapper::WithArgs { program, .. } => program, - } - } - - pub fn args(&self) -> &[String] { - match self { - CommandWrapper::Just(_) => &[], - CommandWrapper::WithArgs { args, .. } => args, - } - } -} - -/// Newtype for implementing deserialize on glutin Mods -/// -/// Our deserialize impl wouldn't be covered by a derive(Deserialize); see the -/// impl below. -#[derive(Debug, Copy, Clone, Hash, Default, Eq, PartialEq)] -pub struct ModsWrapper(ModifiersState); - -impl ModsWrapper { - pub fn into_inner(self) -> ModifiersState { - self.0 - } -} - -impl<'a> de::Deserialize<'a> for ModsWrapper { - fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error> - where - D: de::Deserializer<'a>, - { - struct ModsVisitor; - - impl<'a> Visitor<'a> for ModsVisitor { - type Value = ModsWrapper; - - fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("Some subset of Command|Shift|Super|Alt|Option|Control") - } - - fn visit_str<E>(self, value: &str) -> ::std::result::Result<ModsWrapper, E> - where - E: de::Error, - { - let mut res = ModifiersState::default(); - for modifier in value.split('|') { - match modifier.trim().to_lowercase().as_str() { - "command" | "super" => res.logo = true, - "shift" => res.shift = true, - "alt" | "option" => res.alt = true, - "control" => res.ctrl = true, - "none" => (), - _ => error!("Unknown modifier {:?}", modifier), - } - } - - Ok(ModsWrapper(res)) - } - } - - deserializer.deserialize_str(ModsVisitor) - } -} diff --git a/alacritty_terminal/src/config/colors.rs b/alacritty_terminal/src/config/colors.rs index a9e7a6de..35c03684 100644 --- a/alacritty_terminal/src/config/colors.rs +++ b/alacritty_terminal/src/config/colors.rs @@ -1,10 +1,11 @@ +use log::error; use serde::{Deserialize, Deserializer}; -use crate::config::failure_default; +use crate::config::{failure_default, LOG_TARGET_CONFIG}; use crate::term::color::Rgb; #[serde(default)] -#[derive(Deserialize, Debug, Default, PartialEq, Eq)] +#[derive(Deserialize, Clone, Debug, Default, PartialEq, Eq)] pub struct Colors { #[serde(deserialize_with = "failure_default")] pub primary: PrimaryColors, @@ -33,7 +34,7 @@ impl Colors { } #[serde(default)] -#[derive(Deserialize, Default, Debug, PartialEq, Eq)] +#[derive(Deserialize, Clone, Default, Debug, PartialEq, Eq)] pub struct IndexedColor { #[serde(deserialize_with = "deserialize_color_index")] pub index: u8, @@ -50,6 +51,7 @@ where Ok(index) => { if index < 16 { error!( + target: LOG_TARGET_CONFIG, "Problem with config: indexed_color's index is {}, but a value bigger than 15 \ was expected; ignoring setting", index @@ -62,7 +64,7 @@ where } }, Err(err) => { - error!("Problem with config: {}; ignoring setting", err); + error!(target: LOG_TARGET_CONFIG, "Problem with config: {}; ignoring setting", err); // Return value out of range to ignore this color Ok(0) @@ -89,7 +91,7 @@ pub struct SelectionColors { } #[serde(default)] -#[derive(Deserialize, Debug, PartialEq, Eq)] +#[derive(Deserialize, Clone, Debug, PartialEq, Eq)] pub struct PrimaryColors { #[serde(default = "default_background", deserialize_with = "failure_default")] pub background: Rgb, @@ -121,7 +123,7 @@ fn default_foreground() -> Rgb { } /// The 8-colors sections of config -#[derive(Deserialize, Debug, PartialEq, Eq)] +#[derive(Deserialize, Clone, Debug, PartialEq, Eq)] pub struct AnsiColors { #[serde(deserialize_with = "failure_default")] pub black: Rgb, @@ -141,7 +143,7 @@ pub struct AnsiColors { pub white: Rgb, } -#[derive(Deserialize, Debug, PartialEq, Eq)] +#[derive(Deserialize, Clone, Debug, PartialEq, Eq)] struct NormalColors(AnsiColors); impl Default for NormalColors { @@ -159,7 +161,7 @@ impl Default for NormalColors { } } -#[derive(Deserialize, Debug, PartialEq, Eq)] +#[derive(Deserialize, Clone, Debug, PartialEq, Eq)] struct BrightColors(AnsiColors); impl Default for BrightColors { diff --git a/alacritty_terminal/src/config/debug.rs b/alacritty_terminal/src/config/debug.rs index b7d1144f..f3489693 100644 --- a/alacritty_terminal/src/config/debug.rs +++ b/alacritty_terminal/src/config/debug.rs @@ -1,7 +1,7 @@ -use log::LevelFilter; -use serde::Deserializer; +use log::{error, LevelFilter}; +use serde::{Deserialize, Deserializer}; -use crate::config::failure_default; +use crate::config::{failure_default, LOG_TARGET_CONFIG}; /// Debugging options #[serde(default)] @@ -54,7 +54,10 @@ where "debug" => LevelFilter::Debug, "trace" => LevelFilter::Trace, level => { - error!("Problem with config: invalid log level {}; using level Warn", level); + error!( + target: LOG_TARGET_CONFIG, + "Problem with config: invalid log level {}; using level Warn", level + ); default_log_level() }, }) diff --git a/alacritty_terminal/src/config/font.rs b/alacritty_terminal/src/config/font.rs index 6148c982..a8a76c15 100644 --- a/alacritty_terminal/src/config/font.rs +++ b/alacritty_terminal/src/config/font.rs @@ -1,12 +1,13 @@ use std::fmt; use font::Size; +use log::error; use serde::de::Visitor; use serde::{Deserialize, Deserializer}; #[cfg(target_os = "macos")] use crate::config::DefaultTrueBool; -use crate::config::{failure_default, Delta}; +use crate::config::{failure_default, Delta, LOG_TARGET_CONFIG}; /// Font config /// @@ -202,7 +203,12 @@ impl DeserializeSize for Size { Ok(size) => Ok(size), Err(err) => { let size = default_font_size(); - error!("Problem with config: {}; using size {}", err, size.as_f32_pts()); + error!( + target: LOG_TARGET_CONFIG, + "Problem with config: {}; using size {}", + err, + size.as_f32_pts() + ); Ok(size) }, } diff --git a/alacritty_terminal/src/config/mod.rs b/alacritty_terminal/src/config/mod.rs index ac945e9b..cd900373 100644 --- a/alacritty_terminal/src/config/mod.rs +++ b/alacritty_terminal/src/config/mod.rs @@ -17,42 +17,38 @@ use std::collections::HashMap; use std::fmt::Display; use std::path::PathBuf; +use log::error; +use serde::de::DeserializeOwned; use serde::{Deserialize, Deserializer}; use serde_yaml::Value; -mod bindings; mod colors; mod debug; mod font; -mod monitor; -mod mouse; mod scrolling; -#[cfg(test)] -mod test; mod visual_bell; mod window; use crate::ansi::{Color, CursorStyle, NamedColor}; -use crate::input::{Binding, KeyBinding, MouseBinding}; -pub use crate::config::bindings::Key; pub use crate::config::colors::Colors; pub use crate::config::debug::Debug; pub use crate::config::font::{Font, FontDescription}; -pub use crate::config::monitor::Monitor; -pub use crate::config::mouse::{ClickHandler, Mouse}; pub use crate::config::scrolling::Scrolling; pub use crate::config::visual_bell::{VisualBellAnimation, VisualBellConfig}; -pub use crate::config::window::{Decorations, Dimensions, StartupMode, WindowConfig}; +pub use crate::config::window::{Decorations, Dimensions, StartupMode, WindowConfig, DEFAULT_NAME}; use crate::term::color::Rgb; pub static DEFAULT_ALACRITTY_CONFIG: &str = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/../alacritty.yml")); +pub const LOG_TARGET_CONFIG: &str = "alacritty_config"; const MAX_SCROLLBACK_LINES: u32 = 100_000; +pub type MockConfig = Config<HashMap<String, serde_yaml::Value>>; + /// Top-level config type #[derive(Debug, PartialEq, Deserialize)] -pub struct Config { +pub struct Config<T> { /// Pixel padding #[serde(default, deserialize_with = "failure_default")] pub padding: Option<Delta<u8>>, @@ -80,20 +76,9 @@ pub struct Config { #[serde(default, deserialize_with = "failure_default")] pub window: WindowConfig, - /// Keybindings - #[serde(default = "default_key_bindings", deserialize_with = "deserialize_key_bindings")] - pub key_bindings: Vec<KeyBinding>, - - /// Bindings for the mouse - #[serde(default = "default_mouse_bindings", deserialize_with = "deserialize_mouse_bindings")] - pub mouse_bindings: Vec<MouseBinding>, - #[serde(default, deserialize_with = "failure_default")] pub selection: Selection, - #[serde(default, deserialize_with = "failure_default")] - pub mouse: Mouse, - /// Path to a shell program to run on startup #[serde(default, deserialize_with = "from_string_or_deserialize")] pub shell: Option<Shell<'static>>, @@ -144,6 +129,10 @@ pub struct Config { #[serde(default, deserialize_with = "failure_default")] pub debug: Debug, + /// Additional configuration options not directly required by the terminal + #[serde(flatten)] + pub ui_config: T, + // TODO: DEPRECATED #[serde(default, deserialize_with = "failure_default")] pub render_timer: Option<bool>, @@ -153,13 +142,13 @@ pub struct Config { pub persistent_logging: Option<bool>, } -impl Default for Config { +impl<T: DeserializeOwned> Default for Config<T> { fn default() -> Self { serde_yaml::from_str(DEFAULT_ALACRITTY_CONFIG).expect("default config is invalid") } } -impl Config { +impl<T> Config<T> { pub fn tabspaces(&self) -> usize { self.tabspaces.0 } @@ -236,49 +225,6 @@ impl Config { } } -fn default_key_bindings() -> Vec<KeyBinding> { - bindings::default_key_bindings() -} - -fn default_mouse_bindings() -> Vec<MouseBinding> { - bindings::default_mouse_bindings() -} - -fn deserialize_key_bindings<'a, D>(deserializer: D) -> Result<Vec<KeyBinding>, D::Error> -where - D: Deserializer<'a>, -{ - deserialize_bindings(deserializer, bindings::default_key_bindings()) -} - -fn deserialize_mouse_bindings<'a, D>(deserializer: D) -> Result<Vec<MouseBinding>, D::Error> -where - D: Deserializer<'a>, -{ - deserialize_bindings(deserializer, bindings::default_mouse_bindings()) -} - -fn deserialize_bindings<'a, D, T>( - deserializer: D, - mut default: Vec<Binding<T>>, -) -> Result<Vec<Binding<T>>, D::Error> -where - D: Deserializer<'a>, - T: Copy + Eq + std::hash::Hash + std::fmt::Debug, - Binding<T>: Deserialize<'a>, -{ - let mut bindings: Vec<Binding<T>> = failure_default(deserializer)?; - - // Remove matching default bindings - for binding in bindings.iter() { - default.retain(|b| !b.triggers_match(binding)); - } - - bindings.extend(default); - - Ok(bindings) -} - #[serde(default)] #[derive(Deserialize, Default, Clone, Debug, PartialEq, Eq)] pub struct Selection { @@ -324,7 +270,7 @@ impl Cursor { } } -#[derive(Debug, Deserialize, PartialEq, Eq)] +#[derive(Clone, Debug, Deserialize, PartialEq, Eq)] pub struct Shell<'a> { pub program: Cow<'a, str>, @@ -397,7 +343,7 @@ impl<'a> Deserialize<'a> for Alpha { } } -#[derive(Deserialize, Debug, PartialEq, Eq)] +#[derive(Deserialize, Copy, Clone, Debug, PartialEq, Eq)] struct Tabspaces(usize); impl Default for Tabspaces { @@ -420,7 +366,7 @@ where T: Default, E: Display, { - error!("Problem with config: {}; using default value", err); + error!(target: LOG_TARGET_CONFIG, "Problem with config: {}; using default value", err); T::default() } diff --git a/alacritty_terminal/src/config/monitor.rs b/alacritty_terminal/src/config/monitor.rs deleted file mode 100644 index 6d2ab41a..00000000 --- a/alacritty_terminal/src/config/monitor.rs +++ /dev/null @@ -1,79 +0,0 @@ -use std::path::PathBuf; -use std::sync::mpsc; -use std::time::Duration; - -use notify::{watcher, DebouncedEvent, RecursiveMode, Watcher}; - -pub struct Monitor { - _thread: ::std::thread::JoinHandle<()>, - rx: mpsc::Receiver<PathBuf>, -} - -pub trait OnConfigReload { - fn on_config_reload(&mut self); -} - -impl OnConfigReload for crate::display::Notifier { - fn on_config_reload(&mut self) { - self.notify(); - } -} - -impl Monitor { - /// Get pending config changes - pub fn pending(&self) -> Option<PathBuf> { - let mut config = None; - while let Ok(new) = self.rx.try_recv() { - config = Some(new); - } - - config - } - - pub fn new<H, P>(path: P, mut handler: H) -> Monitor - where - H: OnConfigReload + Send + 'static, - P: Into<PathBuf>, - { - let path = path.into(); - - let (config_tx, config_rx) = mpsc::channel(); - - Monitor { - _thread: crate::util::thread::spawn_named("config watcher", move || { - let (tx, rx) = mpsc::channel(); - // The Duration argument is a debouncing period. - let mut watcher = - watcher(tx, Duration::from_millis(10)).expect("Unable to spawn file watcher"); - let config_path = ::std::fs::canonicalize(path).expect("canonicalize config path"); - - // Get directory of config - let mut parent = config_path.clone(); - parent.pop(); - - // Watch directory - watcher - .watch(&parent, RecursiveMode::NonRecursive) - .expect("watch alacritty.yml dir"); - - loop { - match rx.recv().expect("watcher event") { - DebouncedEvent::Rename(..) => continue, - DebouncedEvent::Write(path) - | DebouncedEvent::Create(path) - | DebouncedEvent::Chmod(path) => { - if path != config_path { - continue; - } - - let _ = config_tx.send(path); - handler.on_config_reload(); - }, - _ => {}, - } - } - }), - rx: config_rx, - } - } -} diff --git a/alacritty_terminal/src/config/mouse.rs b/alacritty_terminal/src/config/mouse.rs deleted file mode 100644 index 7a04cbe7..00000000 --- a/alacritty_terminal/src/config/mouse.rs +++ /dev/null @@ -1,108 +0,0 @@ -use std::time::Duration; - -use glutin::ModifiersState; -use serde::{Deserialize, Deserializer}; - -use crate::config::bindings::{CommandWrapper, ModsWrapper}; -use crate::config::failure_default; - -#[serde(default)] -#[derive(Default, Clone, Debug, Deserialize, PartialEq, Eq)] -pub struct Mouse { - #[serde(deserialize_with = "failure_default")] - pub double_click: ClickHandler, - #[serde(deserialize_with = "failure_default")] - pub triple_click: ClickHandler, - #[serde(deserialize_with = "failure_default")] - pub hide_when_typing: bool, - #[serde(deserialize_with = "failure_default")] - pub url: Url, -} - -#[serde(default)] -#[derive(Clone, Debug, Deserialize, PartialEq, Eq)] -pub struct Url { - // Program for opening links - #[serde(deserialize_with = "deserialize_launcher")] - pub launcher: Option<CommandWrapper>, - - // Modifier used to open links - #[serde(deserialize_with = "failure_default")] - modifiers: ModsWrapper, -} - -impl Url { - pub fn mods(&self) -> ModifiersState { - self.modifiers.into_inner() - } -} - -fn deserialize_launcher<'a, D>( - deserializer: D, -) -> ::std::result::Result<Option<CommandWrapper>, D::Error> -where - D: Deserializer<'a>, -{ - let default = Url::default().launcher; - - // Deserialize to generic value - let val = serde_yaml::Value::deserialize(deserializer)?; - - // Accept `None` to disable the launcher - if val.as_str().filter(|v| v.to_lowercase() == "none").is_some() { - return Ok(None); - } - - match <Option<CommandWrapper>>::deserialize(val) { - Ok(launcher) => Ok(launcher), - Err(err) => { - error!("Problem with config: {}; using {}", err, default.clone().unwrap().program()); - Ok(default) - }, - } -} - -impl Default for Url { - fn default() -> Url { - Url { - #[cfg(not(any(target_os = "macos", windows)))] - launcher: Some(CommandWrapper::Just(String::from("xdg-open"))), - #[cfg(target_os = "macos")] - launcher: Some(CommandWrapper::Just(String::from("open"))), - #[cfg(windows)] - launcher: Some(CommandWrapper::Just(String::from("explorer"))), - modifiers: Default::default(), - } - } -} - -#[serde(default)] -#[derive(Clone, Debug, Deserialize, PartialEq, Eq)] -pub struct ClickHandler { - #[serde(deserialize_with = "deserialize_duration_ms")] - pub threshold: Duration, -} - -impl Default for ClickHandler { - fn default() -> Self { - ClickHandler { threshold: default_threshold_ms() } - } -} - -fn default_threshold_ms() -> Duration { - Duration::from_millis(300) -} - -fn deserialize_duration_ms<'a, D>(deserializer: D) -> ::std::result::Result<Duration, D::Error> -where - D: Deserializer<'a>, -{ - let value = serde_yaml::Value::deserialize(deserializer)?; - match u64::deserialize(value) { - Ok(threshold_ms) => Ok(Duration::from_millis(threshold_ms)), - Err(err) => { - error!("Problem with config: {}; using default value", err); - Ok(default_threshold_ms()) - }, - } -} diff --git a/alacritty_terminal/src/config/scrolling.rs b/alacritty_terminal/src/config/scrolling.rs index d62b102f..8471fcd7 100644 --- a/alacritty_terminal/src/config/scrolling.rs +++ b/alacritty_terminal/src/config/scrolling.rs @@ -1,6 +1,7 @@ +use log::error; use serde::{Deserialize, Deserializer}; -use crate::config::{failure_default, MAX_SCROLLBACK_LINES}; +use crate::config::{failure_default, LOG_TARGET_CONFIG, MAX_SCROLLBACK_LINES}; /// Struct for scrolling related settings #[serde(default)] @@ -63,9 +64,11 @@ impl<'de> Deserialize<'de> for ScrollingHistory { Ok(lines) => { if lines > MAX_SCROLLBACK_LINES { error!( + target: LOG_TARGET_CONFIG, "Problem with config: scrollback size is {}, but expected a maximum of \ {}; using {1} instead", - lines, MAX_SCROLLBACK_LINES, + lines, + MAX_SCROLLBACK_LINES, ); Ok(ScrollingHistory(MAX_SCROLLBACK_LINES)) } else { @@ -73,7 +76,10 @@ impl<'de> Deserialize<'de> for ScrollingHistory { } }, Err(err) => { - error!("Problem with config: {}; using default value", err); + error!( + target: LOG_TARGET_CONFIG, + "Problem with config: {}; using default value", err + ); Ok(Default::default()) }, } diff --git a/alacritty_terminal/src/config/test.rs b/alacritty_terminal/src/config/test.rs deleted file mode 100644 index e7890922..00000000 --- a/alacritty_terminal/src/config/test.rs +++ /dev/null @@ -1,22 +0,0 @@ -use crate::config::{Config, DEFAULT_ALACRITTY_CONFIG}; - -#[test] -fn parse_config() { - let config: Config = - ::serde_yaml::from_str(DEFAULT_ALACRITTY_CONFIG).expect("deserialize config"); - - // Sanity check that mouse bindings are being parsed - assert!(!config.mouse_bindings.is_empty()); - - // Sanity check that key bindings are being parsed - assert!(!config.key_bindings.is_empty()); -} - -#[test] -fn default_match_empty() { - let default = Config::default(); - - let empty = serde_yaml::from_str("key: val\n").unwrap(); - - assert_eq!(default, empty); -} diff --git a/alacritty_terminal/src/config/visual_bell.rs b/alacritty_terminal/src/config/visual_bell.rs index 3a31b24a..8981c929 100644 --- a/alacritty_terminal/src/config/visual_bell.rs +++ b/alacritty_terminal/src/config/visual_bell.rs @@ -1,10 +1,12 @@ use std::time::Duration; +use serde::Deserialize; + use crate::config::failure_default; use crate::term::color::Rgb; #[serde(default)] -#[derive(Debug, Deserialize, PartialEq, Eq)] +#[derive(Deserialize, Clone, Debug, PartialEq, Eq)] pub struct VisualBellConfig { /// Visual bell animation function #[serde(deserialize_with = "failure_default")] diff --git a/alacritty_terminal/src/config/window.rs b/alacritty_terminal/src/config/window.rs index 7ca90a5b..f470f936 100644 --- a/alacritty_terminal/src/config/window.rs +++ b/alacritty_terminal/src/config/window.rs @@ -1,8 +1,12 @@ +use serde::Deserialize; + use crate::config::{ failure_default, from_string_or_deserialize, option_explicit_none, Delta, FromString, }; use crate::index::{Column, Line}; -use crate::window::DEFAULT_NAME; + +/// Default Alacritty name, used for window title and class. +pub const DEFAULT_NAME: &str = "Alacritty"; #[serde(default)] #[derive(Deserialize, Debug, Clone, Default, PartialEq, Eq)] |