diff options
author | Christian Duerr <chrisduerr@users.noreply.github.com> | 2018-07-21 17:17:41 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-07-21 17:17:41 +0000 |
commit | f50ca1a54c94fe324d22d985c1acae1ff7c16a80 (patch) | |
tree | 7fc2e79f7dccf512fe71f841ef5434e0b1d2b5d7 /src | |
parent | b05ad74fe6d42ce0f913e02ef633ca119fc0b43e (diff) | |
download | alacritty-f50ca1a54c94fe324d22d985c1acae1ff7c16a80.tar.gz alacritty-f50ca1a54c94fe324d22d985c1acae1ff7c16a80.zip |
Scrollback cleanup
There were some unneeded codeblocks and TODO/XXX comments in the code
that have been removed. All issues marked with TODO/XXX have either been
already resolved or tracking issues exist.
Diffstat (limited to 'src')
-rw-r--r-- | src/ansi.rs | 8 | ||||
-rw-r--r-- | src/cli.rs | 22 | ||||
-rw-r--r-- | src/config.rs | 60 | ||||
-rw-r--r-- | src/display.rs | 13 | ||||
-rw-r--r-- | src/event.rs | 34 | ||||
-rw-r--r-- | src/grid/mod.rs | 25 | ||||
-rw-r--r-- | src/grid/row.rs | 3 | ||||
-rw-r--r-- | src/grid/storage.rs | 22 | ||||
-rw-r--r-- | src/grid/tests.rs | 4 | ||||
-rw-r--r-- | src/index.rs | 22 | ||||
-rw-r--r-- | src/input.rs | 51 | ||||
-rw-r--r-- | src/lib.rs | 12 | ||||
-rw-r--r-- | src/locale.rs | 1 | ||||
-rw-r--r-- | src/logging.rs | 2 | ||||
-rw-r--r-- | src/main.rs | 11 | ||||
-rw-r--r-- | src/renderer/mod.rs | 14 | ||||
-rw-r--r-- | src/selection.rs | 11 | ||||
-rw-r--r-- | src/term/mod.rs | 136 | ||||
-rw-r--r-- | src/tty.rs | 2 | ||||
-rw-r--r-- | src/util.rs | 19 | ||||
-rw-r--r-- | src/window.rs | 30 |
21 files changed, 298 insertions, 204 deletions
diff --git a/src/ansi.rs b/src/ansi.rs index dbc361a8..e37e25f1 100644 --- a/src/ansi.rs +++ b/src/ansi.rs @@ -561,8 +561,8 @@ pub enum NamedColor { } impl NamedColor { - pub fn to_bright(&self) -> Self { - match *self { + pub fn to_bright(self) -> Self { + match self { NamedColor::Black => NamedColor::BrightBlack, NamedColor::Red => NamedColor::BrightRed, NamedColor::Green => NamedColor::BrightGreen, @@ -583,8 +583,8 @@ impl NamedColor { } } - pub fn to_dim(&self) -> Self { - match *self { + pub fn to_dim(self) -> Self { + match self { NamedColor::Black => NamedColor::DimBlack, NamedColor::Red => NamedColor::DimRed, NamedColor::Green => NamedColor::DimGreen, @@ -15,18 +15,18 @@ extern crate log; use clap::{Arg, App}; use index::{Line, Column}; use config::{Dimensions, Shell}; +use window::{DEFAULT_TITLE, DEFAULT_CLASS}; use std::path::{Path, PathBuf}; use std::borrow::Cow; -const DEFAULT_TITLE: &str = "Alacritty"; - /// Options specified on the command line pub struct Options { pub live_config_reload: Option<bool>, pub print_events: bool, pub ref_test: bool, pub dimensions: Option<Dimensions>, - pub title: String, + pub title: Option<String>, + pub class: Option<String>, pub log_level: log::LevelFilter, pub command: Option<Shell<'static>>, pub working_dir: Option<PathBuf>, @@ -40,7 +40,8 @@ impl Default for Options { print_events: false, ref_test: false, dimensions: None, - title: DEFAULT_TITLE.to_owned(), + title: None, + class: None, log_level: log::LevelFilter::Warn, command: None, working_dir: None, @@ -79,8 +80,12 @@ impl Options { .arg(Arg::with_name("title") .long("title") .short("t") - .default_value(DEFAULT_TITLE) - .help("Defines the window title")) + .takes_value(true) + .help(&format!("Defines the window title [default: {}]", DEFAULT_TITLE))) + .arg(Arg::with_name("class") + .long("class") + .takes_value(true) + .help(&format!("Defines window class on X11 [default: {}]", DEFAULT_CLASS))) .arg(Arg::with_name("q") .short("q") .multiple(true) @@ -132,9 +137,8 @@ impl Options { } } - if let Some(title) = matches.value_of("title") { - options.title = title.to_owned(); - } + options.class = matches.value_of("class").map(|c| c.to_owned()); + options.title = matches.value_of("title").map(|t| t.to_owned()); match matches.occurrences_of("q") { 0 => {}, diff --git a/src/config.rs b/src/config.rs index b9c943ee..7d8600f4 100644 --- a/src/config.rs +++ b/src/config.rs @@ -23,6 +23,7 @@ use notify::{Watcher, watcher, DebouncedEvent, RecursiveMode}; use glutin::ModifiersState; +use cli::Options; use input::{Action, Binding, MouseBinding, KeyBinding}; use index::{Line, Column}; use ansi::CursorStyle; @@ -224,7 +225,7 @@ impl Alpha { } #[inline] - pub fn get(&self) -> f32 { + pub fn get(self) -> f32 { self.0 } @@ -1446,6 +1447,14 @@ impl Config { Ok(config) } + /// Overrides the `dynamic_title` configuration based on `--title`. + pub fn update_dynamic_title(mut self, options: &Options) -> Self { + if options.title.is_some() { + self.dynamic_title = false; + } + self + } + fn read_file<P: AsRef<Path>>(path: P) -> Result<String> { let mut f = fs::File::open(path)?; let mut contents = String::new(); @@ -1609,7 +1618,10 @@ pub struct Font { glyph_offset: Delta<i8>, #[serde(default="true_bool", deserialize_with = "default_true_bool")] - use_thin_strokes: bool + use_thin_strokes: bool, + + #[serde(default="true_bool", deserialize_with = "default_true_bool")] + scale_with_dpi: bool, } fn default_bold_desc() -> FontDescription { @@ -1662,6 +1674,11 @@ impl Font { .. self } } + + /// Check whether dpi should be applied + pub fn scale_with_dpi(&self) -> bool { + self.scale_with_dpi + } } #[cfg(target_os = "macos")] @@ -1673,8 +1690,9 @@ impl Default for Font { italic: FontDescription::new_with_family("Menlo"), size: Size::new(11.0), use_thin_strokes: true, + scale_with_dpi: true, + glyph_offset: Default::default(), offset: Default::default(), - glyph_offset: Default::default() } } } @@ -1688,8 +1706,9 @@ impl Default for Font { italic: FontDescription::new_with_family("monospace"), size: Size::new(11.0), use_thin_strokes: false, + scale_with_dpi: true, + glyph_offset: Default::default(), offset: Default::default(), - glyph_offset: Default::default() } } } @@ -1771,6 +1790,7 @@ impl Monitor { #[cfg(test)] mod tests { + use cli::Options; use super::Config; #[cfg(target_os="macos")] @@ -1791,9 +1811,29 @@ mod tests { // Sanity check that key bindings are being parsed assert!(!config.key_bindings.is_empty()); } + + #[test] + fn dynamic_title_ignoring_options_by_default() { + let config: Config = ::serde_yaml::from_str(ALACRITTY_YML) + .expect("deserialize config"); + let old_dynamic_title = config.dynamic_title; + let options = Options::default(); + let config = config.update_dynamic_title(&options); + assert_eq!(old_dynamic_title, config.dynamic_title); + } + + #[test] + fn dynamic_title_overridden_by_options() { + let config: Config = ::serde_yaml::from_str(ALACRITTY_YML) + .expect("deserialize config"); + let mut options = Options::default(); + options.title = Some("foo".to_owned()); + let config = config.update_dynamic_title(&options); + assert!(!config.dynamic_title); + } } -#[cfg_attr(feature = "clippy", allow(enum_variant_names))] +#[cfg_attr(feature = "cargo-clippy", allow(enum_variant_names))] #[derive(Deserialize, Copy, Clone)] enum Key { Key1, @@ -1947,13 +1987,16 @@ enum Key { WebStop, Yen, Caret, + Copy, + Paste, + Cut, } impl Key { - fn to_glutin_key(&self) -> ::glutin::VirtualKeyCode { + fn to_glutin_key(self) -> ::glutin::VirtualKeyCode { use ::glutin::VirtualKeyCode::*; // Thank you, vim macros! - match *self { + match self { Key::Key1 => Key1, Key::Key2 => Key2, Key::Key3 => Key3, @@ -2105,6 +2148,9 @@ impl Key { Key::WebStop => WebStop, Key::Yen => Yen, Key::Caret => Caret, + Key::Copy => Copy, + Key::Paste => Paste, + Key::Cut => Cut, } } } diff --git a/src/display.rs b/src/display.rs index 5e540a8b..4c3ffed1 100644 --- a/src/display.rs +++ b/src/display.rs @@ -136,12 +136,16 @@ impl Display { let render_timer = config.render_timer(); // Create the window where Alacritty will be displayed - let mut window = Window::new(&options.title, config.window())?; + let mut window = Window::new(&options, config.window())?; // get window properties for initializing the other subsystems let mut viewport_size = window.inner_size_pixels() .expect("glutin returns window size"); - let dpr = window.hidpi_factor(); + let dpr = if config.font().scale_with_dpi() { + window.hidpi_factor() + } else { + 1.0 + }; info!("device_pixel_ratio: {}", dpr); @@ -149,7 +153,7 @@ impl Display { let mut renderer = QuadRenderer::new(config, viewport_size)?; let (glyph_cache, cell_width, cell_height) = - Self::new_glyph_cache(&window, &mut renderer, config)?; + Self::new_glyph_cache(dpr, &mut renderer, config)?; let dimensions = options.dimensions() @@ -210,11 +214,10 @@ impl Display { }) } - fn new_glyph_cache(window : &Window, renderer : &mut QuadRenderer, config: &Config) + fn new_glyph_cache(dpr: f32, renderer: &mut QuadRenderer, config: &Config) -> Result<(GlyphCache, f32, f32), Error> { let font = config.font().clone(); - let dpr = window.hidpi_factor(); let rasterizer = font::Rasterizer::new(dpr, config.use_thin_strokes())?; // Initialize glyph cache diff --git a/src/event.rs b/src/event.rs index ff95c880..3af417bd 100644 --- a/src/event.rs +++ b/src/event.rs @@ -59,17 +59,15 @@ impl<'a, N: Notify + 'a> input::ActionContext for ActionContext<'a, N> { } fn copy_selection(&self, buffer: ::copypasta::Buffer) { - self.terminal - .selection_to_string() - .map(|selected| { - if !selected.is_empty() { - Clipboard::new() - .and_then(|mut clipboard| clipboard.store(selected, buffer)) - .unwrap_or_else(|err| { - warn!("Error storing selection to clipboard. {}", Red(err)); - }); - } - }); + if let Some(selected) = self.terminal.selection_to_string() { + if !selected.is_empty() { + Clipboard::new() + .and_then(|mut clipboard| clipboard.store(selected, buffer)) + .unwrap_or_else(|err| { + warn!("Error storing selection to clipboard. {}", Red(err)); + }); + } + } } fn clear_selection(&mut self) { @@ -113,7 +111,7 @@ impl<'a, N: Notify + 'a> input::ActionContext for ActionContext<'a, N> { self.terminal.pixels_to_coords(self.mouse.x as usize, self.mouse.y as usize) } - fn change_font_size(&mut self, delta: i8) { + fn change_font_size(&mut self, delta: f32) { self.terminal.change_font_size(delta); } @@ -241,7 +239,7 @@ impl<N: Notify> Processor<N> { resize_tx, ref_test, mouse: Default::default(), - size_info: size_info, + size_info, hide_cursor_when_typing: config.hide_cursor_when_typing(), hide_cursor: false, received_count: 0, @@ -298,7 +296,7 @@ impl<N: Notify> Processor<N> { }, KeyboardInput { input, .. } => { let glutin::KeyboardInput { state, virtual_keycode, modifiers, .. } = input; - processor.process_key(state, virtual_keycode, &modifiers); + processor.process_key(state, virtual_keycode, modifiers); if state == ElementState::Pressed { // Hide cursor while typing *hide_cursor = true; @@ -308,9 +306,11 @@ impl<N: Notify> Processor<N> { processor.received_char(c); }, MouseInput { state, button, modifiers, .. } => { - *hide_cursor = false; - processor.mouse_input(state, button, modifiers); - processor.ctx.terminal.dirty = true; + if *window_is_focused { + *hide_cursor = false; + processor.mouse_input(state, button, modifiers); + processor.ctx.terminal.dirty = true; + } }, CursorMoved { position: (x, y), modifiers, .. } => { let x = limit(x as i32, 0, processor.ctx.size_info.width as i32); diff --git a/src/grid/mod.rs b/src/grid/mod.rs index 949a5ed5..ef587ffd 100644 --- a/src/grid/mod.rs +++ b/src/grid/mod.rs @@ -102,6 +102,7 @@ pub struct GridIterator<'a, T: 'a> { pub cur: Point<usize>, } +#[derive(Copy, Clone)] pub enum Scroll { Lines(isize), PageUp, @@ -396,6 +397,7 @@ impl<T: Copy + Clone> Grid<T> { } } +#[cfg_attr(feature = "cargo-clippy", allow(len_without_is_empty))] impl<T> Grid<T> { #[inline] pub fn num_lines(&self) -> index::Line { @@ -437,15 +439,6 @@ impl<T> Grid<T> { pub fn contains(&self, point: &Point) -> bool { self.lines > point.line && self.cols > point.col } - - // /// Swap two lines in the grid - // /// - // /// This could have used slice::swap internally, but we are able to have - // /// better error messages by doing the bounds checking ourselves. - // #[inline] - // pub fn swap_lines(&mut self, src: index::Line, dst: index::Line) { - // self.raw.swap(*src, *dst); - // } } impl<'a, T> Iterator for GridIterator<'a, T> { @@ -566,10 +559,10 @@ impl<'a, T> RegionMut<'a, T> { pub trait IndexRegion<I, T> { /// Get an immutable region of Self - fn region<'a>(&'a self, _: I) -> Region<'a, T>; + fn region(&self, _: I) -> Region<T>; /// Get a mutable region of Self - fn region_mut<'a>(&'a mut self, _: I) -> RegionMut<'a, T>; + fn region_mut(&mut self, _: I) -> RegionMut<T>; } impl<T> IndexRegion<Range<Line>, T> for Grid<T> { @@ -772,13 +765,11 @@ impl<'a, T: Copy + 'a> Iterator for DisplayIter<'a, T> { // Update line/col to point to next item self.col += 1; - if self.col == self.grid.num_cols() { - if self.offset != self.limit { - self.offset -= 1; + if self.col == self.grid.num_cols() && self.offset != self.limit { + self.offset -= 1; - self.col = Column(0); - self.line = Line(*self.grid.lines - 1 - (self.offset - self.limit)); - } + self.col = Column(0); + self.line = Line(*self.grid.lines - 1 - (self.offset - self.limit)); } item diff --git a/src/grid/row.rs b/src/grid/row.rs index ea8804a7..69a4f2b2 100644 --- a/src/grid/row.rs +++ b/src/grid/row.rs @@ -71,6 +71,7 @@ impl<T: Copy + Clone> Row<T> { } } +#[cfg_attr(feature = "cargo-clippy", allow(len_without_is_empty))] impl<T> Row<T> { pub fn shrink(&mut self, cols: Column) { while self.len() != *cols { @@ -84,7 +85,7 @@ impl<T> Row<T> { self.inner.len() } - pub fn iter<'a>(&'a self) -> slice::Iter<'a, T> { + pub fn iter(&self) -> slice::Iter<T> { self.inner.iter() } } diff --git a/src/grid/storage.rs b/src/grid/storage.rs index 5d6cb936..6a453da6 100644 --- a/src/grid/storage.rs +++ b/src/grid/storage.rs @@ -68,12 +68,12 @@ impl<T: PartialEq> ::std::cmp::PartialEq for Storage<T> { // Smaller Zero (3): // 7 8 9 | 0 1 2 3 | 4 5 6 // C3 C3 C3 | C1 C1 C1 C1 | C2 C2 C2 - &bigger.inner[bigger_zero..] - == &smaller.inner[smaller_zero..smaller_zero + (len - bigger_zero)] - && &bigger.inner[..bigger_zero - smaller_zero] - == &smaller.inner[smaller_zero + (len - bigger_zero)..] - && &bigger.inner[bigger_zero - smaller_zero..bigger_zero] - == &smaller.inner[..smaller_zero] + bigger.inner[bigger_zero..] + == smaller.inner[smaller_zero..smaller_zero + (len - bigger_zero)] + && bigger.inner[..bigger_zero - smaller_zero] + == smaller.inner[smaller_zero + (len - bigger_zero)..] + && bigger.inner[bigger_zero - smaller_zero..bigger_zero] + == smaller.inner[..smaller_zero] } } @@ -84,11 +84,8 @@ impl<T> Storage<T> { T: Clone, { // Allocate all lines in the buffer, including scrollback history - // - // TODO (jwilm) Allocating each line at this point is expensive and - // delays startup. A nice solution might be having `Row` delay - // allocation until it's actually used. let inner = vec![template; cap]; + Storage { inner, zero: 0, @@ -124,7 +121,7 @@ impl<T> Storage<T> { } /// Grow the number of lines in the buffer, filling new lines with the template - pub fn grow_lines(&mut self, growage: usize, template_row: Row<T>) + fn grow_lines(&mut self, growage: usize, template_row: Row<T>) where T: Clone, { @@ -225,9 +222,6 @@ impl<T> Storage<T> { /// The default implementation from swap generates 8 movups and 4 movaps /// instructions. This implementation achieves the swap in only 8 movups /// instructions. - /// - // TODO Once specialization is available, Storage<T> can be fully generic - // again instead of enforcing inner: Vec<Row<T>>. pub fn swap(&mut self, a: usize, b: usize) { debug_assert!(::std::mem::size_of::<Row<T>>() == 32); diff --git a/src/grid/tests.rs b/src/grid/tests.rs index 435f0c3d..e136e3b3 100644 --- a/src/grid/tests.rs +++ b/src/grid/tests.rs @@ -20,7 +20,7 @@ use index::{Point, Line, Column}; // Scroll up moves lines upwards #[test] fn scroll_up() { - println!(""); + println!(); let mut grid = Grid::new(Line(10), Column(1), 0, 0); for i in 0..10 { @@ -58,7 +58,7 @@ fn scroll_up() { // Scroll down moves lines downwards #[test] fn scroll_down() { - println!(""); + println!(); let mut grid = Grid::new(Line(10), Column(1), 0, 0); for i in 0..10 { diff --git a/src/index.rs b/src/index.rs index ada5f5b1..ab8e7416 100644 --- a/src/index.rs +++ b/src/index.rs @@ -270,7 +270,7 @@ macro_rules! inclusive { match *self { Empty { .. } => (0, Some(0)), - NonEmpty { ref start, ref end } => { + NonEmpty { start, end } => { let added = $steps_add_one(start, end); match added { Some(hint) => (hint.saturating_add(1), hint.checked_add(1)), @@ -283,9 +283,9 @@ macro_rules! inclusive { } } -fn steps_add_one_u8(start: &u8, end: &u8) -> Option<usize> { - if *start < *end { - Some((*end - *start) as usize) +fn steps_add_one_u8(start: u8, end: u8) -> Option<usize> { + if start < end { + Some((end - start) as usize) } else { None } @@ -330,11 +330,11 @@ macro_rules! ops { impl $ty { #[inline] #[allow(trivial_numeric_casts)] - fn steps_between(start: &$ty, end: &$ty, by: &$ty) -> Option<usize> { - if *by == $construct(0) { return None; } - if *start < *end { + fn steps_between(start: $ty, end: $ty, by: $ty) -> Option<usize> { + if by == $construct(0) { return None; } + if start < end { // Note: We assume $t <= usize here - let diff = (*end - *start).0; + let diff = (end - start).0; let by = by.0; if diff % by > 0 { Some(diff / by + 1) @@ -347,8 +347,8 @@ macro_rules! ops { } #[inline] - fn steps_between_by_one(start: &$ty, end: &$ty) -> Option<usize> { - Self::steps_between(start, end, &$construct(1)) + fn steps_between_by_one(start: $ty, end: $ty) -> Option<usize> { + Self::steps_between(start, end, $construct(1)) } } @@ -366,7 +366,7 @@ macro_rules! ops { } #[inline] fn size_hint(&self) -> (usize, Option<usize>) { - match Self::Item::steps_between_by_one(&self.0.start, &self.0.end) { + match Self::Item::steps_between_by_one(self.0.start, self.0.end) { Some(hint) => (hint, Some(hint)), None => (0, None) } diff --git a/src/input.rs b/src/input.rs index 2d647114..f2337d6a 100644 --- a/src/input.rs +++ b/src/input.rs @@ -35,6 +35,8 @@ use term::SizeInfo; use term::mode::TermMode; use util::fmt::Red; +pub const FONT_SIZE_STEP: f32 = 0.5; + /// Processes input from glutin. /// /// An escape sequence may be emitted in case specific keys or key combinations @@ -64,7 +66,7 @@ pub trait ActionContext { fn received_count(&mut self) -> &mut usize; fn suppress_chars(&mut self) -> &mut bool; fn last_modifiers(&mut self) -> &mut ModifiersState; - fn change_font_size(&mut self, delta: i8); + fn change_font_size(&mut self, delta: f32); fn reset_font_size(&mut self); fn scroll(&mut self, scroll: Scroll); } @@ -103,15 +105,15 @@ impl<T: Eq> Binding<T> { fn is_triggered_by( &self, mode: TermMode, - mods: &ModifiersState, + mods: ModifiersState, input: &T ) -> bool { // Check input first since bindings are stored in one big list. This is // the most likely item to fail so prioritizing it here allows more // checks to be short circuited. self.trigger == *input && - self.mode_matches(&mode) && - self.not_mode_matches(&mode) && + self.mode_matches(mode) && + self.not_mode_matches(mode) && self.mods_match(mods) } } @@ -124,12 +126,12 @@ impl<T> Binding<T> { } #[inline] - fn mode_matches(&self, mode: &TermMode) -> bool { + fn mode_matches(&self, mode: TermMode) -> bool { self.mode.is_empty() || mode.intersects(self.mode) } #[inline] - fn not_mode_matches(&self, mode: &TermMode) -> bool { + fn not_mode_matches(&self, mode: TermMode) -> bool { self.notmode.is_empty() || !mode.intersects(self.notmode) } @@ -137,10 +139,10 @@ impl<T> Binding<T> { /// /// Optimized to use single check instead of four (one per modifier) #[inline] - fn mods_match(&self, mods: &ModifiersState) -> bool { - debug_assert!(4 == mem::size_of::<ModifiersState>()); + fn mods_match(&self, mods: ModifiersState) -> bool { + assert_eq_size!(ModifiersState, u32); unsafe { - mem::transmute_copy::<_, u32>(&self.mods) == mem::transmute_copy::<_, u32>(mods) + mem::transmute_copy::<_, u32>(&self.mods) == mem::transmute_copy::<_, u32>(&mods) } } } @@ -243,10 +245,10 @@ impl Action { ::std::process::exit(0); }, Action::IncreaseFontSize => { - ctx.change_font_size(1); + ctx.change_font_size(FONT_SIZE_STEP); }, Action::DecreaseFontSize => { - ctx.change_font_size(-1); + ctx.change_font_size(-FONT_SIZE_STEP); } Action::ResetFontSize => { ctx.reset_font_size(); @@ -507,19 +509,19 @@ impl<'a, A: ActionContext + 'a> Processor<'a, A> { let mouse_modes = TermMode::MOUSE_REPORT_CLICK | TermMode::MOUSE_DRAG | TermMode::MOUSE_MOTION; // Make sure the new and deprecated setting are both allowed - let faux_scrollback_lines = self.mouse_config + let faux_scrolling_lines = self.mouse_config .faux_scrollback_lines .unwrap_or(self.scrolling_config.faux_multiplier as usize); if self.ctx.terminal_mode().intersects(mouse_modes) { self.mouse_report(code, ElementState::Pressed, modifiers); } else if self.ctx.terminal_mode().contains(TermMode::ALT_SCREEN) - && faux_scrollback_lines > 0 && !modifiers.shift + && faux_scrolling_lines > 0 && !modifiers.shift { // Faux scrolling let cmd = code + 1; // 64 + 1 = A, 65 + 1 = B - let mut content = Vec::with_capacity(faux_scrollback_lines as usize * 3); - for _ in 0..faux_scrollback_lines { + let mut content = Vec::with_capacity(faux_scrolling_lines as usize * 3); + for _ in 0..faux_scrolling_lines { content.push(0x1b); content.push(b'O'); content.push(cmd); @@ -527,7 +529,8 @@ impl<'a, A: ActionContext + 'a> Processor<'a, A> { self.ctx.write_to_pty(content); } else { for _ in 0..scroll_multiplier { - self.ctx.scroll(Scroll::Lines(-((code as isize) * 2 - 129))); + // Transform the reported button codes 64 and 65 into 1 and -1 lines to scroll + self.ctx.scroll(Scroll::Lines(-(code as isize * 2 - 129))); } } } @@ -567,7 +570,7 @@ impl<'a, A: ActionContext + 'a> Processor<'a, A> { return; } - self.process_mouse_bindings(&ModifiersState::default(), button); + self.process_mouse_bindings(ModifiersState::default(), button); } /// Process key input @@ -577,11 +580,11 @@ impl<'a, A: ActionContext + 'a> Processor<'a, A> { &mut self, state: ElementState, key: Option<VirtualKeyCode>, - mods: &ModifiersState, + mods: ModifiersState, ) { match (key, state) { (Some(key), ElementState::Pressed) => { - *self.ctx.last_modifiers() = *mods; + *self.ctx.last_modifiers() = mods; *self.ctx.received_count() = 0; *self.ctx.suppress_chars() = false; @@ -623,7 +626,7 @@ impl<'a, A: ActionContext + 'a> Processor<'a, A> { /// for its action to be executed. /// /// Returns true if an action is executed. - fn process_key_bindings(&mut self, mods: &ModifiersState, key: VirtualKeyCode) -> bool { + fn process_key_bindings(&mut self, mods: ModifiersState, key: VirtualKeyCode) -> bool { for binding in self.key_bindings { if binding.is_triggered_by(self.ctx.terminal_mode(), mods, &key) { // binding was triggered; run the action @@ -641,7 +644,7 @@ impl<'a, A: ActionContext + 'a> Processor<'a, A> { /// for its action to be executed. /// /// Returns true if an action is executed. - fn process_mouse_bindings(&mut self, mods: &ModifiersState, button: MouseButton) -> bool { + fn process_mouse_bindings(&mut self, mods: ModifiersState, button: MouseButton) -> bool { for binding in self.mouse_bindings { if binding.is_triggered_by(self.ctx.terminal_mode(), mods, &button) { // binding was triggered; run the action @@ -741,7 +744,7 @@ mod tests { fn last_modifiers(&mut self) -> &mut ModifiersState { &mut self.last_modifiers } - fn change_font_size(&mut self, _delta: i8) { + fn change_font_size(&mut self, _delta: f32) { } fn reset_font_size(&mut self) { } @@ -824,9 +827,9 @@ mod tests { #[test] fn $name() { if $triggers { - assert!($binding.is_triggered_by($mode, &$mods, &KEY)); + assert!($binding.is_triggered_by($mode, $mods, &KEY)); } else { - assert!(!$binding.is_triggered_by($mode, &$mods, &KEY)); + assert!(!$binding.is_triggered_by($mode, $mods, &KEY)); } } } @@ -13,12 +13,7 @@ // limitations under the License. // //! Alacritty - The GPU Enhanced Terminal -#![cfg_attr(feature = "clippy", feature(plugin))] -#![cfg_attr(feature = "clippy", plugin(clippy))] -#![cfg_attr(feature = "clippy", deny(clippy))] -#![cfg_attr(feature = "clippy", deny(enum_glob_use))] -#![cfg_attr(feature = "clippy", deny(if_not_else))] -#![cfg_attr(feature = "clippy", deny(wrong_pub_self_convention))] +#![cfg_attr(feature = "cargo-clippy", deny(clippy, if_not_else, enum_glob_use, wrong_pub_self_convention))] #![cfg_attr(feature = "nightly", feature(core_intrinsics))] #![cfg_attr(all(test, feature = "bench"), feature(test))] @@ -26,6 +21,7 @@ #[macro_use] extern crate clap; #[macro_use] extern crate log; #[macro_use] extern crate serde_derive; +#[macro_use] extern crate static_assertions; #[cfg(any(target_os = "linux", target_os = "freebsd", target_os="dragonfly", target_os="openbsd"))] extern crate x11_dl; @@ -115,11 +111,9 @@ impl Mul<f32> for Rgb { } -#[cfg_attr(feature = "clippy", allow(too_many_arguments))] -#[cfg_attr(feature = "clippy", allow(doc_markdown))] -#[cfg_attr(feature = "clippy", allow(unreadable_literal))] #[allow(unused_mut)] pub mod gl { #![allow(non_upper_case_globals)] + #![cfg_attr(feature = "cargo-clippy", allow(clippy))] include!(concat!(env!("OUT_DIR"), "/gl_bindings.rs")); } diff --git a/src/locale.rs b/src/locale.rs index 9fcd2db2..bea68cad 100644 --- a/src/locale.rs +++ b/src/locale.rs @@ -11,6 +11,7 @@ // 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. +#![cfg_attr(feature = "cargo-clippy", allow(let_unit_value))] #![cfg(target_os = "macos")] use libc::{LC_CTYPE, setlocale}; use std::ffi::{CString, CStr}; diff --git a/src/logging.rs b/src/logging.rs index 5691eb78..a691778a 100644 --- a/src/logging.rs +++ b/src/logging.rs @@ -29,7 +29,7 @@ pub struct Logger<T> { impl<T: Send + io::Write> Logger<T> { // False positive, see: https://github.com/rust-lang-nursery/rust-clippy/issues/734 - #[cfg_attr(feature = "clippy", allow(new_ret_no_self))] + #[cfg_attr(feature = "cargo-clippy", allow(new_ret_no_self))] pub fn new(output: T, level: log::LevelFilter) -> Logger<io::LineWriter<T>> { log::set_max_level(level); Logger { diff --git a/src/main.rs b/src/main.rs index 77cb4949..1508103c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,12 +13,7 @@ // limitations under the License. // //! Alacritty - The GPU Enhanced Terminal -#![cfg_attr(feature = "clippy", feature(plugin))] -#![cfg_attr(feature = "clippy", plugin(clippy))] -#![cfg_attr(feature = "clippy", deny(clippy))] -#![cfg_attr(feature = "clippy", deny(enum_glob_use))] -#![cfg_attr(feature = "clippy", deny(if_not_else))] -#![cfg_attr(feature = "clippy", deny(wrong_pub_self_convention))] +#![cfg_attr(feature = "cargo-clippy", deny(clippy, if_not_else, enum_glob_use, wrong_pub_self_convention))] #![cfg_attr(feature = "nightly", feature(core_intrinsics))] #![cfg_attr(all(test, feature = "bench"), feature(test))] @@ -49,7 +44,7 @@ use alacritty::util::fmt::Red; fn main() { // Load command line options and config let options = cli::Options::load(); - let config = load_config(&options); + let config = load_config(&options).update_dynamic_title(&options); // Switch to home directory #[cfg(target_os = "macos")] @@ -183,7 +178,7 @@ fn run(mut config: Config, options: &cli::Options) -> Result<(), Box<Error>> { .as_ref() .and_then(|monitor| monitor.pending_config()) { - config = new_config; + config = new_config.update_dynamic_title(&options); display.update_config(&config); processor.update_config(&config); terminal.update_config(&config); diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index ed61f7f5..00ac9eb2 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -183,7 +183,7 @@ impl GlyphCache { // Need to load at least one glyph for the face before calling metrics. // The glyph requested here ('m' at the time of writing) has no special // meaning. - rasterizer.get_glyph(&GlyphKey { font_key: regular, c: 'm', size: font.size() })?; + rasterizer.get_glyph(GlyphKey { font_key: regular, c: 'm', size: font.size() })?; let metrics = rasterizer.metrics(regular)?; let mut cache = GlyphCache { @@ -211,7 +211,7 @@ impl GlyphCache { ) { let size = self.font_size; for i in RangeInclusive::new(32u8, 128u8) { - self.get(&GlyphKey { + self.get(GlyphKey { font_key: font, c: i as char, size, @@ -273,14 +273,14 @@ impl GlyphCache { .expect("metrics load since font is loaded at glyph cache creation") } - pub fn get<'a, L>(&'a mut self, glyph_key: &GlyphKey, loader: &mut L) -> &'a Glyph + pub fn get<'a, L>(&'a mut self, glyph_key: GlyphKey, loader: &mut L) -> &'a Glyph where L: LoadGlyph { let glyph_offset = self.glyph_offset; let rasterizer = &mut self.rasterizer; let metrics = &self.metrics; self.cache - .entry(*glyph_key) + .entry(glyph_key) .or_insert_with(|| { let mut rasterized = rasterizer.get_glyph(glyph_key) .unwrap_or_else(|_| Default::default()); @@ -306,7 +306,7 @@ impl GlyphCache { let font = font.to_owned().with_size(size); info!("Font size changed: {:?}", font.size); let (regular, bold, italic) = Self::compute_font_keys(&font, &mut self.rasterizer)?; - self.rasterizer.get_glyph(&GlyphKey { font_key: regular, c: 'm', size: font.size() })?; + self.rasterizer.get_glyph(GlyphKey { font_key: regular, c: 'm', size: font.size() })?; let metrics = self.rasterizer.metrics(regular)?; self.font_size = font.size; @@ -842,7 +842,7 @@ impl<'a> RenderApi<'a> { // Add cell to batch { - let glyph = glyph_cache.get(&glyph_key, self); + let glyph = glyph_cache.get(glyph_key, self); self.add_render_item(&cell, glyph); } @@ -856,7 +856,7 @@ impl<'a> RenderApi<'a> { c: '_' }; - let underscore = glyph_cache.get(&glyph_key, self); + let underscore = glyph_cache.get(glyph_key, self); self.add_render_item(&cell, underscore); } } diff --git a/src/selection.rs b/src/selection.rs index dca16e26..702599e3 100644 --- a/src/selection.rs +++ b/src/selection.rs @@ -157,8 +157,8 @@ impl Selection { Selection::Semantic { ref region } => { Selection::span_semantic(grid, region) }, - Selection::Lines { ref region, ref initial_line } => { - Selection::span_lines(grid, region, *initial_line) + Selection::Lines { ref region, initial_line } => { + Selection::span_lines(grid, region, initial_line) } } } @@ -253,13 +253,12 @@ impl Selection { // Remove last cell if selection ends to the left of a cell if front_side == Side::Left && start != end { - if front.col != Column(0) { - front.col -= 1; - } // Special case when selection starts to left of first cell - else { + if front.col == Column(0) { front.col = cols - 1; front.line += 1; + } else { + front.col -= 1; } } diff --git a/src/term/mod.rs b/src/term/mod.rs index 9f8506d1..3cdd5ff3 100644 --- a/src/term/mod.rs +++ b/src/term/mod.rs @@ -30,6 +30,7 @@ use selection::{self, Selection, Locations}; use config::{Config, VisualBellAnimation}; use {MouseCursor, Rgb}; use copypasta::{Clipboard, Load, Store}; +use input::FONT_SIZE_STEP; pub mod cell; pub mod color; @@ -129,7 +130,7 @@ impl<'a> RenderableCellsIter<'a> { let inner = grid.display_iter(); let mut selection_range = None; - selection.map(|loc| { + if let Some(loc) = selection { // Get on-screen lines of the selection's locations let start_line = grid.buffer_line_to_visible(loc.start.line); let end_line = grid.buffer_line_to_visible(loc.end.line); @@ -171,17 +172,17 @@ impl<'a> RenderableCellsIter<'a> { // Update the selection selection_range = Some(RangeInclusive::new(start, end)); } - }); + } RenderableCellsIter { - cursor: cursor, - cursor_offset: cursor_offset, - grid: grid, - inner: inner, - mode: mode, + cursor, + cursor_offset, + grid, + inner, + mode, selection: selection_range, - config: config, - colors: colors, + config, + colors, cursor_cells: ArrayDeque::new(), }.initialize(cursor_style) } @@ -313,9 +314,9 @@ impl<'a> RenderableCellsIter<'a> { self.mode.contains(mode::TermMode::SHOW_CURSOR) && self.grid.contains(self.cursor) } - fn compute_fg_rgb(&self, fg: &Color, cell: &Cell) -> Rgb { + fn compute_fg_rgb(&self, fg: Color, cell: &Cell) -> Rgb { use self::cell::Flags; - match *fg { + match fg { Color::Spec(rgb) => rgb, Color::Named(ansi) => { match (self.config.draw_bold_text_with_bright_colors(), cell.flags & Flags::DIM_BOLD) { @@ -346,15 +347,15 @@ impl<'a> RenderableCellsIter<'a> { } #[inline] - fn compute_bg_alpha(&self, bg: &Color) -> f32 { - match *bg { + fn compute_bg_alpha(&self, bg: Color) -> f32 { + match bg { Color::Named(NamedColor::Background) => 0.0, _ => 1.0 } } - fn compute_bg_rgb(&self, bg: &Color) -> Rgb { - match *bg { + fn compute_bg_rgb(&self, bg: Color) -> Rgb { + match bg { Color::Spec(rgb) => rgb, Color::Named(ansi) => self.colors[ansi], Color::Indexed(idx) => self.colors[idx], @@ -403,8 +404,6 @@ impl<'a> Iterator for RenderableCellsIter<'a> { let index = Linear(cell.line.0 * self.grid.num_cols().0 + cell.column.0); - // XXX (jwilm) selection temp disabled - // let selected = self.selection.as_ref() .map(|range| range.contains_(index)) .unwrap_or(false); @@ -429,13 +428,13 @@ impl<'a> Iterator for RenderableCellsIter<'a> { fg_rgb = self.colors[NamedColor::Background]; bg_alpha = 1.0 } else { - bg_rgb = self.compute_fg_rgb(&cell.fg, &cell); - fg_rgb = self.compute_bg_rgb(&cell.bg); + bg_rgb = self.compute_fg_rgb(cell.fg, &cell); + fg_rgb = self.compute_bg_rgb(cell.bg); } } else { - fg_rgb = self.compute_fg_rgb(&cell.fg, &cell); - bg_rgb = self.compute_bg_rgb(&cell.bg); - bg_alpha = self.compute_bg_alpha(&cell.bg); + fg_rgb = self.compute_fg_rgb(cell.fg, &cell); + bg_rgb = self.compute_bg_rgb(cell.bg); + bg_alpha = self.compute_bg_alpha(cell.bg); } return Some(RenderableCell { @@ -445,7 +444,7 @@ impl<'a> Iterator for RenderableCellsIter<'a> { c: cell.c, fg: fg_rgb, bg: bg_rgb, - bg_alpha: bg_alpha, + bg_alpha, }) } } @@ -890,10 +889,10 @@ impl Term { } } - pub fn change_font_size(&mut self, delta: i8) { - // Saturating addition with minimum font size 1 - let new_size = self.font_size + Size::new(f32::from(delta)); - self.font_size = max(new_size, Size::new(1.)); + pub fn change_font_size(&mut self, delta: f32) { + // Saturating addition with minimum font size FONT_SIZE_STEP + let new_size = self.font_size + Size::new(delta); + self.font_size = max(new_size, Size::new(FONT_SIZE_STEP)); self.dirty = true; } @@ -1157,18 +1156,6 @@ impl Term { self.tabs = IndexRange::from(Column(0)..self.grid.num_cols()) .map(|i| (*i as usize) % self.tabspaces == 0) .collect::<Vec<bool>>(); - - // if num_lines > old_lines { - // // Make sure bottom of terminal is clear - // let template = self.cursor.template; - // self.grid - // .region_mut((self.cursor.point.line + 1)..) - // .each(|c| c.reset(&template)); - // self.alt_grid - // .region_mut((self.cursor_save_alt.point.line + 1)..) - // .each(|c| c.reset(&template)); - // } - } #[inline] @@ -2002,6 +1989,9 @@ mod tests { use ansi::{Handler, CharsetIndex, StandardCharset}; use selection::Selection; use std::mem; + use input::FONT_SIZE_STEP; + use font::Size; + use config::Config; #[test] fn semantic_selection_works() { @@ -2105,6 +2095,72 @@ mod tests { assert_eq!(term.grid()[&cursor].c, '▒'); } + + fn change_font_size_works(font_size: f32) { + let size = SizeInfo { + width: 21.0, + height: 51.0, + cell_width: 3.0, + cell_height: 3.0, + padding_x: 0.0, + padding_y: 0.0, + }; + let config: Config = Default::default(); + let mut term: Term = Term::new(&config, size); + term.change_font_size(font_size); + + let expected_font_size: Size = config.font().size() + Size::new(font_size); + assert_eq!(term.font_size, expected_font_size); + } + + #[test] + fn increase_font_size_works() { + change_font_size_works(10.0); + } + + #[test] + fn decrease_font_size_works() { + change_font_size_works(-10.0); + } + + #[test] + fn prevent_font_below_threshold_works() { + let size = SizeInfo { + width: 21.0, + height: 51.0, + cell_width: 3.0, + cell_height: 3.0, + padding_x: 0.0, + padding_y: 0.0, + }; + let config: Config = Default::default(); + let mut term: Term = Term::new(&config, size); + + term.change_font_size(-100.0); + + let expected_font_size: Size = Size::new(FONT_SIZE_STEP); + assert_eq!(term.font_size, expected_font_size); + } + + #[test] + fn reset_font_size_works() { + let size = SizeInfo { + width: 21.0, + height: 51.0, + cell_width: 3.0, + cell_height: 3.0, + padding_x: 0.0, + padding_y: 0.0, + }; + let config: Config = Default::default(); + let mut term: Term = Term::new(&config, size); + + term.change_font_size(10.0); + term.reset_font_size(); + + let expected_font_size: Size = config.font().size(); + assert_eq!(term.font_size, expected_font_size); + } } #[cfg(all(test, feature = "bench"))] @@ -2161,7 +2217,7 @@ mod benches { mem::swap(&mut terminal.grid, &mut grid); b.iter(|| { - let iter = terminal.renderable_cells(&config, None, false); + let iter = terminal.renderable_cells(&config, false); for cell in iter { test::black_box(cell); } @@ -117,7 +117,7 @@ fn set_controlling_terminal(fd: c_int) { // based on architecture (32/64). So a generic cast is used to make sure // there are no issues. To allow such a generic cast the clippy warning // is disabled. - #[cfg_attr(feature = "clippy", allow(cast_lossless))] + #[cfg_attr(feature = "cargo-clippy", allow(cast_lossless))] libc::ioctl(fd, TIOCSCTTY as _, 0) }; diff --git a/src/util.rs b/src/util.rs index f51a41f8..6065e01b 100644 --- a/src/util.rs +++ b/src/util.rs @@ -15,7 +15,6 @@ use std::cmp; #[cfg(not(feature = "nightly"))] #[inline(always)] -#[cfg_attr(feature = "clippy", allow(inline_always))] pub unsafe fn unlikely(x: bool) -> bool { x } @@ -74,24 +73,12 @@ pub mod fmt { /// Write a `Display` or `Debug` escaped with Red pub struct Red => "31"; + /// Write a `Display` or `Debug` escaped with Green + pub struct Green => "32"; + /// Write a `Display` or `Debug` escaped with Yellow pub struct Yellow => "33"; } - - /// Write a `Display` or `Debug` escaped with Red - pub struct Green<T>(pub T); - - impl<T: fmt::Display> fmt::Display for Green<T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "\x1b[32m{}\x1b[0m", self.0) - } - } - - impl<T: fmt::Debug> fmt::Debug for Green<T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "\x1b[32m{:?}\x1b[0m", self.0) - } - } } #[cfg(test)] diff --git a/src/window.rs b/src/window.rs index 987332e0..1903360f 100644 --- a/src/window.rs +++ b/src/window.rs @@ -22,8 +22,26 @@ use glutin::GlContext; use MouseCursor; +use cli::Options; use config::WindowConfig; +/// Default text for the window's title bar, if not overriden. +/// +/// In X11, this the default value for the `WM_NAME` property. +pub const DEFAULT_TITLE: &str = "Alacritty"; + +/// Default text for general window class, X11 specific. +/// +/// In X11, this is the default value for the `WM_CLASS` property. The +/// second value of `WM_CLASS` is **never** changed to anything but +/// the default value. +/// +/// ```ignore +/// $ xprop | grep WM_CLASS +/// WM_CLASS(STRING) = "Alacritty", "Alacritty" +/// ``` +pub const DEFAULT_CLASS: &str = "Alacritty"; + /// Window errors #[derive(Debug)] pub enum Error { @@ -199,17 +217,19 @@ impl Window { /// /// This creates a window and fully initializes a window. pub fn new( - title: &str, + options: &Options, window_config: &WindowConfig, ) -> Result<Window> { let event_loop = EventsLoop::new(); + let title = options.title.as_ref().map_or(DEFAULT_TITLE, |t| t); + let class = options.class.as_ref().map_or(DEFAULT_CLASS, |c| c); let window_builder = WindowBuilder::new() .with_title(title) .with_visibility(false) .with_transparency(true) .with_decorations(window_config.decorations()); - let window_builder = Window::platform_builder_ext(window_builder); + let window_builder = Window::platform_builder_ext(window_builder, &class); let window = create_gl_window(window_builder.clone(), &event_loop, false) .or_else(|_| create_gl_window(window_builder, &event_loop, true))?; window.show(); @@ -322,13 +342,13 @@ impl Window { } #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd"))] - fn platform_builder_ext(window_builder: WindowBuilder) -> WindowBuilder { + fn platform_builder_ext(window_builder: WindowBuilder, wm_class: &str) -> WindowBuilder { use glutin::os::unix::WindowBuilderExt; - window_builder.with_class("alacritty".to_owned(), "Alacritty".to_owned()) + window_builder.with_class(wm_class.to_owned(), "Alacritty".to_owned()) } #[cfg(not(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd")))] - fn platform_builder_ext(window_builder: WindowBuilder) -> WindowBuilder { + fn platform_builder_ext(window_builder: WindowBuilder, _: &str) -> WindowBuilder { window_builder } |