diff --git a/.travis.yml b/.travis.yml index e1c9ce5..6749cfe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,6 +35,10 @@ matrix: os: windows env: CLIPPY=true rust: stable + - name: "Rustfmt" + os: linux + env: RUSTFMT=true + rust: nightly allow_failures: - rust: nightly diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8818e38..bb5010a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -89,7 +89,7 @@ Changes compared to the latest Alacritty release which have a direct effect on t ### Style -Alacritty currently does not have any automatically enforced style guidelines. As a result of that, it is not possible to run `rustfmt` on existing files. New code should however follow the default ruleset of `rustfmt` and for newly created files it is possible to run the `rustfmt` tool directly. +All Alacritty changes are automatically verified by CI to conform to its rustfmt guidelines. If a CI build is failing because of formatting issues, you can install rustfmt using `rustup component add rustfmt` and then format all code using `cargo fmt`. # Contact diff --git a/build.rs b/build.rs index 4036dad..1a12a67 100644 --- a/build.rs +++ b/build.rs @@ -14,10 +14,10 @@ #[cfg(windows)] use embed_resource; #[cfg(windows)] -use tempfile; -#[cfg(windows)] use reqwest; #[cfg(windows)] +use tempfile; +#[cfg(windows)] use zip; use gl_generator::{Api, Fallbacks, GlobalGenerator, Profile, Registry}; @@ -26,25 +26,21 @@ use std::env; use std::fs::File; use std::path::Path; -#[cfg(windows)] -use std::io; #[cfg(windows)] use std::fs::OpenOptions; +#[cfg(windows)] +use std::io; #[cfg(windows)] -const WINPTY_PACKAGE_URL: &str = "https://github.com/rprichard/winpty/releases/download/0.4.3/winpty-0.4.3-msvc2015.zip"; +const WINPTY_PACKAGE_URL: &str = + "https://github.com/rprichard/winpty/releases/download/0.4.3/winpty-0.4.3-msvc2015.zip"; fn main() { let dest = env::var("OUT_DIR").unwrap(); let mut file = File::create(&Path::new(&dest).join("gl_bindings.rs")).unwrap(); - Registry::new( - Api::Gl, - (4, 5), - Profile::Core, - Fallbacks::All, - ["GL_ARB_blend_func_extended"], - ).write_bindings(GlobalGenerator, &mut file) + Registry::new(Api::Gl, (4, 5), Profile::Core, Fallbacks::All, ["GL_ARB_blend_func_extended"]) + .write_bindings(GlobalGenerator, &mut file) .unwrap(); #[cfg(windows)] @@ -68,7 +64,8 @@ fn aquire_winpty_agent(out_path: &Path) { .read(true) .write(true) .create(true) - .open(tmp_dir.path().join("winpty_package.zip")).unwrap(); + .open(tmp_dir.path().join("winpty_package.zip")) + .unwrap(); io::copy(&mut response, &mut file).unwrap(); @@ -77,7 +74,7 @@ fn aquire_winpty_agent(out_path: &Path) { let target = match env::var("TARGET").unwrap().split("-").next().unwrap() { "x86_64" => "x64", "i386" => "ia32", - _ => panic!("architecture has no winpty binary") + _ => panic!("architecture has no winpty binary"), }; let mut winpty_agent = archive.by_name(&format!("{}/bin/winpty-agent.exe", target)).unwrap(); diff --git a/ci/install.sh b/ci/install.sh index af4bb77..ccbe372 100755 --- a/ci/install.sh +++ b/ci/install.sh @@ -1,6 +1,11 @@ #!/bin/bash -# Add clippy for linting with nightly builds +# Add clippy for lint validation if [ "$CLIPPY" == "true" ]; then rustup component add clippy fi + +# Add rustfmt for format validation +if [ "$RUSTFMT" == "true" ]; then + rustup component add rustfmt +fi diff --git a/ci/script.sh b/ci/script.sh index c17bbbd..2199141 100755 --- a/ci/script.sh +++ b/ci/script.sh @@ -9,6 +9,12 @@ if [ "$CLIPPY" == "true" ]; then exit fi +# Run clippy rustfmt +if [ "$RUSTFMT" == "true" ]; then + cargo fmt -- --check + exit +fi + # Run test in release mode if a tag is present, to produce an optimized binary if [ -n "$TRAVIS_TAG" ]; then cargo test --release || error=true diff --git a/copypasta/src/macos.rs b/copypasta/src/macos.rs index 1942ac4..d0ccaec 100644 --- a/copypasta/src/macos.rs +++ b/copypasta/src/macos.rs @@ -4,18 +4,18 @@ //! https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/PasteboardGuide106/Articles/pbReading.html#//apple_ref/doc/uid/TP40008123-SW1 mod ns { - extern crate objc_id; extern crate objc_foundation; + extern crate objc_id; #[link(name = "AppKit", kind = "framework")] - extern {} + extern "C" {} use std::mem; - use objc::runtime::{Class, Object}; + use self::objc_foundation::{INSArray, INSObject, INSString}; + use self::objc_foundation::{NSArray, NSDictionary, NSObject, NSString}; use self::objc_id::{Id, Owned}; - use self::objc_foundation::{NSArray, NSObject, NSDictionary, NSString}; - use self::objc_foundation::{INSString, INSArray, INSObject}; + use objc::runtime::{Class, Object}; /// Rust API for NSPasteboard pub struct Pasteboard(Id); @@ -55,6 +55,7 @@ mod ns { impl PasteboardReadObject for Pasteboard { type Err = ReadStringError; + fn read_object(&self) -> Result { // Get string class; need this for passing to readObjectsForClasses let ns_string_class = match Class::get("NSString") { @@ -133,9 +134,7 @@ mod ns { // The writeObjects method returns true in case of success, and // false otherwise. - let ok: bool = unsafe { - msg_send![self.0, writeObjects:objects] - }; + let ok: bool = unsafe { msg_send![self.0, writeObjects: objects] }; if ok { Ok(()) @@ -175,9 +174,7 @@ mod ns { impl ::std::error::Error for NewPasteboardError { fn description(&self) -> &str { match *self { - NewPasteboardError::GetPasteboardClass => { - "NSPasteboard class not found" - }, + NewPasteboardError::GetPasteboardClass => "NSPasteboard class not found", NewPasteboardError::LoadGeneralPasteboard => { "[NSPasteboard generalPasteboard] failed" }, @@ -209,9 +206,7 @@ mod ns { } }; - let id = unsafe { - Id::from_ptr(ptr) - }; + let id = unsafe { Id::from_ptr(ptr) }; Ok(Pasteboard(id)) } @@ -222,9 +217,7 @@ mod ns { /// This is the first step in providing data on the pasteboard. The /// return value is the change count of the pasteboard pub fn clear_contents(&mut self) -> usize { - unsafe { - msg_send![self.0, clearContents] - } + unsafe { msg_send![self.0, clearContents] } } } } @@ -236,7 +229,6 @@ pub enum Error { WriteString(ns::WriteStringError), } - impl ::std::error::Error for Error { fn cause(&self) -> Option<&::std::error::Error> { match *self { @@ -258,9 +250,7 @@ impl ::std::error::Error for Error { impl ::std::fmt::Display for Error { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { match *self { - Error::CreatePasteboard(ref err) => { - write!(f, "Failed to create pasteboard: {}", err) - }, + Error::CreatePasteboard(ref err) => write!(f, "Failed to create pasteboard: {}", err), Error::ReadString(ref err) => { write!(f, "Failed to read string from pasteboard: {}", err) }, @@ -301,23 +291,23 @@ impl super::Load for Clipboard { fn load_primary(&self) -> Result { use self::ns::PasteboardReadObject; - self.0.read_object() - .map_err(::std::convert::From::from) + self.0.read_object().map_err(::std::convert::From::from) } } impl super::Store for Clipboard { fn store_primary(&mut self, contents: S) -> Result<(), Self::Err> - where S: Into + where + S: Into, { use self::ns::PasteboardWriteObject; - self.0.write_object(contents.into()) - .map_err(::std::convert::From::from) + self.0.write_object(contents.into()).map_err(::std::convert::From::from) } fn store_selection(&mut self, _contents: S) -> Result<(), Self::Err> - where S: Into + where + S: Into, { // No such thing on macOS Ok(()) @@ -327,7 +317,7 @@ impl super::Store for Clipboard { #[cfg(test)] mod tests { use super::Clipboard; - use ::{Load, Store}; + use {Load, Store}; #[test] fn create_clipboard_save_load_contents() { diff --git a/copypasta/src/windows.rs b/copypasta/src/windows.rs index 95e3db5..48b033c 100644 --- a/copypasta/src/windows.rs +++ b/copypasta/src/windows.rs @@ -33,9 +33,7 @@ impl Load for Clipboard { type Err = Error; fn new() -> Result { - ClipboardContext::new() - .map(Clipboard) - .map_err(Error::Clipboard) + ClipboardContext::new().map(Clipboard).map_err(Error::Clipboard) } fn load_primary(&self) -> Result { @@ -56,9 +54,7 @@ impl Store for Clipboard { where S: Into, { - self.0 - .set_contents(contents.into()) - .map_err(Error::Clipboard) + self.0.set_contents(contents.into()).map_err(Error::Clipboard) } /// Sets the secondary clipboard contents @@ -67,8 +63,6 @@ impl Store for Clipboard { where S: Into, { - self.0 - .set_contents(contents.into()) - .map_err(Error::Clipboard) + self.0.set_contents(contents.into()).map_err(Error::Clipboard) } } diff --git a/copypasta/src/x11.rs b/copypasta/src/x11.rs index c7d9c69..3e0d791 100644 --- a/copypasta/src/x11.rs +++ b/copypasta/src/x11.rs @@ -7,10 +7,10 @@ //! //! FIXME: Implement actual X11 clipboard API using the ICCCM reference //! https://tronche.com/gui/x/icccm/ -use std::io; -use std::process::{Output, Command}; -use std::string::FromUtf8Error; use std::ffi::OsStr; +use std::io; +use std::process::{Command, Output}; +use std::string::FromUtf8Error; use super::{Load, Store}; @@ -45,13 +45,11 @@ impl ::std::error::Error for Error { impl ::std::fmt::Display for Error { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { match *self { - Error::Io(ref err) => { - match err.kind() { - io::ErrorKind::NotFound => { - write!(f, "Please install `xclip` to enable clipboard support") - }, - _ => write!(f, "Error calling xclip: {}", err), - } + Error::Io(ref err) => match err.kind() { + io::ErrorKind::NotFound => { + write!(f, "Please install `xclip` to enable clipboard support") + }, + _ => write!(f, "Error calling xclip: {}", err), }, Error::Xclip(ref s) => write!(f, "Error from xclip: {}", s), Error::Utf8(ref err) => write!(f, "Error parsing xclip output: {}", err), @@ -79,17 +77,13 @@ impl Load for Clipboard { } fn load_primary(&self) -> Result { - let output = Command::new("xclip") - .args(&["-o", "-selection", "clipboard"]) - .output()?; + let output = Command::new("xclip").args(&["-o", "-selection", "clipboard"]).output()?; Clipboard::process_xclip_output(output) } fn load_selection(&self) -> Result { - let output = Command::new("xclip") - .args(&["-o"]) - .output()?; + let output = Command::new("xclip").args(&["-o"]).output()?; Clipboard::process_xclip_output(output) } @@ -99,7 +93,8 @@ impl Store for Clipboard { /// Sets the primary clipboard contents #[inline] fn store_primary(&mut self, contents: S) -> Result<(), Self::Err> - where S: Into + where + S: Into, { self.store(contents, &["-i", "-selection", "clipboard"]) } @@ -107,7 +102,8 @@ impl Store for Clipboard { /// Sets the secondary clipboard contents #[inline] fn store_selection(&mut self, contents: S) -> Result<(), Self::Err> - where S: Into + where + S: Into, { self.store(contents, &["-i"]) } @@ -116,26 +112,22 @@ impl Store for Clipboard { impl Clipboard { fn process_xclip_output(output: Output) -> Result { if output.status.success() { - String::from_utf8(output.stdout) - .map_err(::std::convert::From::from) + String::from_utf8(output.stdout).map_err(::std::convert::From::from) } else { - String::from_utf8(output.stderr) - .map_err(::std::convert::From::from) + String::from_utf8(output.stderr).map_err(::std::convert::From::from) } } fn store(&mut self, contents: C, args: &[S]) -> Result<(), Error> - where C: Into, - S: AsRef, + where + C: Into, + S: AsRef, { use std::io::Write; use std::process::{Command, Stdio}; let contents = contents.into(); - let mut child = Command::new("xclip") - .args(args) - .stdin(Stdio::piped()) - .spawn()?; + let mut child = Command::new("xclip").args(args).stdin(Stdio::piped()).spawn()?; if let Some(stdin) = child.stdin.as_mut() { stdin.write_all(contents.as_bytes())?; @@ -154,7 +146,7 @@ impl Clipboard { #[cfg(test)] mod tests { use super::Clipboard; - use ::{Load, Store}; + use {Load, Store}; #[test] fn clipboard_works() { diff --git a/font/src/darwin/byte_order.rs b/font/src/darwin/byte_order.rs index 2ea46fc..382caa3 100644 --- a/font/src/darwin/byte_order.rs +++ b/font/src/darwin/byte_order.rs @@ -40,9 +40,10 @@ pub fn extract_rgb(bytes: &[u8]) -> Vec { #[cfg(target_endian = "big")] pub fn extract_rgb(bytes: Vec) -> Vec { - bytes.into_iter() - .enumerate() - .filter(|&(index, _)| ((index) % 4) != 0) - .map(|(_, val)| val) - .collect::>() + bytes + .into_iter() + .enumerate() + .filter(|&(index, _)| ((index) % 4) != 0) + .map(|(_, val)| val) + .collect::>() } diff --git a/font/src/darwin/mod.rs b/font/src/darwin/mod.rs index 60b1a3e..15a97e2 100644 --- a/font/src/darwin/mod.rs +++ b/font/src/darwin/mod.rs @@ -17,34 +17,37 @@ //! TODO error handling... just search for unwrap. #![allow(improper_ctypes)] use std::collections::HashMap; -use std::ptr; use std::path::PathBuf; +use std::ptr; -use ::{Slant, Weight, Style}; +use {Slant, Style, Weight}; -use core_foundation::string::{CFString}; -use core_foundation::array::{CFIndex, CFArray}; +use core_foundation::array::{CFArray, CFIndex}; +use core_foundation::string::CFString; use core_graphics::base::kCGImageAlphaPremultipliedFirst; use core_graphics::color_space::CGColorSpace; -use core_graphics::context::{CGContext}; +use core_graphics::context::CGContext; use core_graphics::font::{CGFont, CGGlyph}; use core_graphics::geometry::{CGPoint, CGRect, CGSize}; -use core_text::font::{CTFont, new_from_descriptor as ct_new_from_descriptor, cascade_list_for_languages as ct_cascade_list_for_languages}; +use core_text::font::{ + cascade_list_for_languages as ct_cascade_list_for_languages, + new_from_descriptor as ct_new_from_descriptor, CTFont, +}; use core_text::font_collection::create_for_family; use core_text::font_collection::get_family_names as ct_get_family_names; use core_text::font_descriptor::kCTFontDefaultOrientation; use core_text::font_descriptor::kCTFontHorizontalOrientation; use core_text::font_descriptor::kCTFontVerticalOrientation; -use core_text::font_descriptor::{CTFontDescriptor, CTFontOrientation}; use core_text::font_descriptor::SymbolicTraitAccessors; +use core_text::font_descriptor::{CTFontDescriptor, CTFontOrientation}; use euclid::{Point2D, Rect, Size2D}; -use super::{FontDesc, RasterizedGlyph, Metrics, FontKey, GlyphKey}; +use super::{FontDesc, FontKey, GlyphKey, Metrics, RasterizedGlyph}; pub mod byte_order; -use self::byte_order::kCGBitmapByteOrder32Host; use self::byte_order::extract_rgb; +use self::byte_order::kCGBitmapByteOrder32Host; use super::Size; @@ -59,11 +62,11 @@ pub struct Descriptor { display_name: String, font_path: PathBuf, - ct_descriptor: CTFontDescriptor + ct_descriptor: CTFontDescriptor, } impl Descriptor { - fn new(desc:CTFontDescriptor) -> Descriptor { + fn new(desc: CTFontDescriptor) -> Descriptor { Descriptor { family_name: desc.family_name(), font_name: desc.font_name(), @@ -111,16 +114,14 @@ impl ::std::error::Error for Error { impl ::std::fmt::Display for Error { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { match *self { - Error::MissingGlyph(ref c) => { - write!(f, "Glyph not found for char {:?}", c) - }, - Error::MissingFont(ref desc) => { - write!(f, "Couldn't find a font with {}\ - \n\tPlease check the font config in your alacritty.yml.", desc) - }, - Error::FontNotLoaded => { - f.write_str("Tried to use a font that hasn't been loaded") - } + Error::MissingGlyph(ref c) => write!(f, "Glyph not found for char {:?}", c), + Error::MissingFont(ref desc) => write!( + f, + "Couldn't find a font with {}\n\tPlease check the font config in your \ + alacritty.yml.", + desc + ), + Error::FontNotLoaded => f.write_str("Tried to use a font that hasn't been loaded"), } } } @@ -139,50 +140,41 @@ impl ::Rasterize for Rasterizer { /// Get metrics for font specified by FontKey fn metrics(&self, key: FontKey, _size: Size) -> Result { - let font = self.fonts - .get(&key) - .ok_or(Error::FontNotLoaded)?; + let font = self.fonts.get(&key).ok_or(Error::FontNotLoaded)?; Ok(font.metrics()) } fn load_font(&mut self, desc: &FontDesc, size: Size) -> Result { let scaled_size = Size::new(size.as_f32_pts() * self.device_pixel_ratio); - self.keys - .get(&(desc.to_owned(), scaled_size)) - .map(|k| Ok(*k)) - .unwrap_or_else(|| { - let font = self.get_font(desc, size)?; - let key = FontKey::next(); + self.keys.get(&(desc.to_owned(), scaled_size)).map(|k| Ok(*k)).unwrap_or_else(|| { + let font = self.get_font(desc, size)?; + let key = FontKey::next(); - self.fonts.insert(key, font); - self.keys.insert((desc.clone(), scaled_size), key); + self.fonts.insert(key, font); + self.keys.insert((desc.clone(), scaled_size), key); - Ok(key) - }) + Ok(key) + }) } /// Get rasterized glyph for given glyph key fn get_glyph(&mut self, glyph: GlyphKey) -> Result { - // get loaded font - let font = self.fonts - .get(&glyph.font_key) - .ok_or(Error::FontNotLoaded)?; + let font = self.fonts.get(&glyph.font_key).ok_or(Error::FontNotLoaded)?; // first try the font itself as a direct hit - self.maybe_get_glyph(glyph, font) - .unwrap_or_else(|| { - // then try fallbacks - for fallback in &font.fallbacks { - if let Some(result) = self.maybe_get_glyph(glyph, &fallback) { - // found a fallback - return result; - } + self.maybe_get_glyph(glyph, font).unwrap_or_else(|| { + // then try fallbacks + for fallback in &font.fallbacks { + if let Some(result) = self.maybe_get_glyph(glyph, &fallback) { + // found a fallback + return result; } - // no fallback, give up. - Err(Error::MissingGlyph(glyph.c)) - }) + } + // no fallback, give up. + Err(Error::MissingGlyph(glyph.c)) + }) } fn update_dpr(&mut self, device_pixel_ratio: f32) { @@ -195,7 +187,7 @@ impl Rasterizer { &mut self, desc: &FontDesc, style: &str, - size: Size + size: Size, ) -> Result { let descriptors = descriptors_for_family(&desc.name[..]); for descriptor in descriptors { @@ -215,11 +207,11 @@ impl Rasterizer { desc: &FontDesc, slant: Slant, weight: Weight, - size: Size + size: Size, ) -> Result { let bold = match weight { Weight::Bold => true, - _ => false + _ => false, }; let italic = match slant { Slant::Normal => false, @@ -262,7 +254,6 @@ impl Rasterizer { _ => Some(Err(e)), }) } - } /// Specifies the intended rendering orientation of the font for obtaining glyph metrics @@ -302,18 +293,12 @@ pub fn get_family_names() -> Vec { owned_names } - /// Return fallback descriptors for font/language list -fn cascade_list_for_languages( - ct_font: &CTFont, - languages: &[String] -) -> Vec { - +fn cascade_list_for_languages(ct_font: &CTFont, languages: &[String]) -> Vec { // convert language type &Vec -> CFArray - let langarr:CFArray = { - let tmp:Vec = languages.iter() - .map(|language| CFString::new(&language)) - .collect(); + let langarr: CFArray = { + let tmp: Vec = + languages.iter().map(|language| CFString::new(&language)).collect(); CFArray::from_CFTypes(&tmp) }; @@ -321,12 +306,9 @@ fn cascade_list_for_languages( let list = ct_cascade_list_for_languages(ct_font, &langarr); // convert CFArray to Vec - list.into_iter() - .map(|fontdesc| Descriptor::new(fontdesc.clone())) - .collect() + list.into_iter().map(|fontdesc| Descriptor::new(fontdesc.clone())).collect() } - /// Get descriptors for family name pub fn descriptors_for_family(family: &str) -> Vec { let mut out = Vec::new(); @@ -350,7 +332,7 @@ pub fn descriptors_for_family(family: &str) -> Vec { impl Descriptor { /// Create a Font from this descriptor - pub fn to_font(&self, size: f64, load_fallbacks:bool) -> Font { + pub fn to_font(&self, size: f64, load_fallbacks: bool) -> Font { let ct_font = ct_new_from_descriptor(&self.ct_descriptor, size); let cg_font = ct_font.copy_to_CGFont(); @@ -385,7 +367,7 @@ impl Descriptor { fallbacks.insert(0, Font { cg_font: menlo.copy_to_CGFont(), ct_font: menlo, - fallbacks: Vec::new() + fallbacks: Vec::new(), }); fallbacks @@ -395,25 +377,16 @@ impl Descriptor { Vec::new() }; - Font { - ct_font, - cg_font, - fallbacks, - } + Font { ct_font, cg_font, fallbacks } } } impl Font { /// The the bounding rect of a glyph - pub fn bounding_rect_for_glyph( - &self, - orientation: FontOrientation, - index: u32 - ) -> Rect { - let cg_rect = self.ct_font.get_bounding_rects_for_glyphs( - orientation as CTFontOrientation, - &[index as CGGlyph] - ); + pub fn bounding_rect_for_glyph(&self, orientation: FontOrientation, index: u32) -> Rect { + let cg_rect = self + .ct_font + .get_bounding_rects_for_glyphs(orientation as CTFontOrientation, &[index as CGGlyph]); Rect::new( Point2D::new(cg_rect.origin.x, cg_rect.origin.y), @@ -465,12 +438,17 @@ impl Font { FontOrientation::Default as _, &indices[0], ptr::null_mut(), - 1 + 1, ) } } - pub fn get_glyph(&self, character: char, _size: f64, use_thin_strokes: bool) -> Result { + pub fn get_glyph( + &self, + character: char, + _size: f64, + use_thin_strokes: bool, + ) -> Result { // Render custom symbols for underline and beam cursor match character { super::UNDERLINE_CURSOR_CHAR => { @@ -480,7 +458,7 @@ impl Font { let width = self.glyph_advance('0') as i32; // Return the new custom glyph return super::get_underline_cursor_glyph(descent, width); - } + }, super::BEAM_CURSOR_CHAR | super::BOX_CURSOR_CHAR => { // Get the top of the bounding box let metrics = self.metrics(); @@ -496,12 +474,12 @@ impl Font { } else { return super::get_box_cursor_glyph(ascent as i32, height as i32, width); } - } - _ => () + }, + _ => (), } - let glyph_index = self.glyph_index(character) - .ok_or_else(|| Error::MissingGlyph(character))?; + let glyph_index = + self.glyph_index(character).ok_or_else(|| Error::MissingGlyph(character))?; let bounds = self.bounding_rect_for_glyph(Default::default(), glyph_index); @@ -519,7 +497,7 @@ impl Font { height: 0, top: 0, left: 0, - buf: Vec::new() + buf: Vec::new(), }); } @@ -530,17 +508,14 @@ impl Font { 8, // bits per component rasterized_width as usize * 4, &CGColorSpace::create_device_rgb(), - kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host + kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host, ); // Give the context an opaque, black background cg_context.set_rgb_fill_color(0.0, 0.0, 0.0, 1.0); let context_rect = CGRect::new( &CGPoint::new(0.0, 0.0), - &CGSize::new( - f64::from(rasterized_width), - f64::from(rasterized_height) - ) + &CGSize::new(f64::from(rasterized_width), f64::from(rasterized_height)), ); cg_context.fill_rect(context_rect); @@ -560,14 +535,14 @@ impl Font { // Set fill color to white for drawing the glyph cg_context.set_rgb_fill_color(1.0, 1.0, 1.0, 1.0); - let rasterization_origin = CGPoint { - x: f64::from(-rasterized_left), - y: f64::from(rasterized_descent), - }; + let rasterization_origin = + CGPoint { x: f64::from(-rasterized_left), y: f64::from(rasterized_descent) }; - self.ct_font.draw_glyphs(&[glyph_index as CGGlyph], - &[rasterization_origin], - cg_context.clone()); + self.ct_font.draw_glyphs( + &[glyph_index as CGGlyph], + &[rasterization_origin], + cg_context.clone(), + ); let rasterized_pixels = cg_context.data().to_vec(); @@ -586,22 +561,22 @@ impl Font { fn glyph_index(&self, character: char) -> Option { // encode this char as utf-16 let mut buf = [0; 2]; - let encoded:&[u16] = character.encode_utf16(&mut buf); + let encoded: &[u16] = character.encode_utf16(&mut buf); // and use the utf-16 buffer to get the index self.glyph_index_utf16(encoded) } - fn glyph_index_utf16(&self, encoded: &[u16]) -> Option { + fn glyph_index_utf16(&self, encoded: &[u16]) -> Option { // output buffer for the glyph. for non-BMP glyphs, like // emojis, this will be filled with two chars the second // always being a 0. - let mut glyphs:[CGGlyph; 2] = [0; 2]; + let mut glyphs: [CGGlyph; 2] = [0; 2]; let res = unsafe { self.ct_font.get_glyphs_for_characters( encoded.as_ptr(), glyphs.as_mut_ptr(), - encoded.len() as CFIndex + encoded.len() as CFIndex, ) }; @@ -629,9 +604,7 @@ mod tests { println!("{:?}", list); // Check to_font - let fonts = list.iter() - .map(|desc| desc.to_font(72., false)) - .collect::>(); + let fonts = list.iter().map(|desc| desc.to_font(72., false)).collect::>(); for font in fonts { // Get a glyph @@ -649,7 +622,7 @@ mod tests { 101...150 => '~', 151...200 => '*', 201...255 => '#', - _ => unreachable!() + _ => unreachable!(), }; print!("{}", c); } diff --git a/font/src/ft/fc/char_set.rs b/font/src/ft/fc/char_set.rs index 151d14a..310fa18 100644 --- a/font/src/ft/fc/char_set.rs +++ b/font/src/ft/fc/char_set.rs @@ -11,10 +11,10 @@ // 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 foreign_types::{ForeignTypeRef}; +use foreign_types::ForeignTypeRef; -use super::ffi::{FcCharSet, FcCharSetDestroy, FcCharSetAddChar}; -use super::ffi::{FcCharSetCreate}; +use super::ffi::FcCharSetCreate; +use super::ffi::{FcCharSet, FcCharSetAddChar, FcCharSetDestroy}; foreign_type! { type CType = FcCharSet; @@ -37,12 +37,6 @@ impl Default for CharSet { impl CharSetRef { pub fn add(&mut self, glyph: char) -> bool { - unsafe { - FcCharSetAddChar( - self.as_ptr(), - glyph as _ - ) == 1 - } + unsafe { FcCharSetAddChar(self.as_ptr(), glyph as _) == 1 } } } - diff --git a/font/src/ft/fc/config.rs b/font/src/ft/fc/config.rs index 9744b37..12ec284 100644 --- a/font/src/ft/fc/config.rs +++ b/font/src/ft/fc/config.rs @@ -11,10 +11,10 @@ // 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 foreign_types::{ForeignTypeRef}; +use foreign_types::ForeignTypeRef; -use super::{SetName, FontSetRef}; -use super::ffi::{FcConfigGetCurrent, FcConfigGetFonts, FcConfig, FcConfigDestroy}; +use super::ffi::{FcConfig, FcConfigDestroy, FcConfigGetCurrent, FcConfigGetFonts}; +use super::{FontSetRef, SetName}; foreign_type! { type CType = FcConfig; @@ -25,13 +25,10 @@ foreign_type! { pub struct ConfigRef; } - impl Config { /// Get the current configuration pub fn get_current() -> &'static ConfigRef { - unsafe { - ConfigRef::from_ptr(FcConfigGetCurrent()) - } + unsafe { ConfigRef::from_ptr(FcConfigGetCurrent()) } } } diff --git a/font/src/ft/fc/font_set.rs b/font/src/ft/fc/font_set.rs index 4eccd48..aeb3437 100644 --- a/font/src/ft/fc/font_set.rs +++ b/font/src/ft/fc/font_set.rs @@ -15,9 +15,9 @@ use std::ops::Deref; use foreign_types::{ForeignType, ForeignTypeRef}; -use super::{ConfigRef, PatternRef, ObjectSetRef}; +use super::{ConfigRef, ObjectSetRef, PatternRef}; -use super::ffi::{FcFontSetList, FcFontSetDestroy, FcFontSet}; +use super::ffi::{FcFontSet, FcFontSetDestroy, FcFontSetList}; foreign_type! { type CType = FcFontSet; @@ -33,13 +33,13 @@ impl FontSet { config: &ConfigRef, source: &mut FontSetRef, pattern: &PatternRef, - objects: &ObjectSetRef + objects: &ObjectSetRef, ) -> FontSet { let raw = unsafe { FcFontSetList( config.as_ptr(), &mut source.as_ptr(), - 1 /* nsets */, + 1, // nsets pattern.as_ptr(), objects.as_ptr(), ) @@ -56,38 +56,28 @@ pub struct Iter<'a> { } impl<'a> IntoIterator for &'a FontSet { - type Item = &'a PatternRef; type IntoIter = Iter<'a>; + type Item = &'a PatternRef; + fn into_iter(self) -> Iter<'a> { - let num_fonts = unsafe { - (*self.as_ptr()).nfont as isize - }; + let num_fonts = unsafe { (*self.as_ptr()).nfont as isize }; trace!("Number of fonts is {}", num_fonts); - Iter { - font_set: self.deref(), - num_fonts: num_fonts as _, - current: 0, - } + Iter { font_set: self.deref(), num_fonts: num_fonts as _, current: 0 } } } impl<'a> IntoIterator for &'a FontSetRef { - type Item = &'a PatternRef; type IntoIter = Iter<'a>; + type Item = &'a PatternRef; + fn into_iter(self) -> Iter<'a> { - let num_fonts = unsafe { - (*self.as_ptr()).nfont as isize - }; + let num_fonts = unsafe { (*self.as_ptr()).nfont as isize }; trace!("Number of fonts is {}", num_fonts); - Iter { - font_set: self, - num_fonts: num_fonts as _, - current: 0, - } + Iter { font_set: self, num_fonts: num_fonts as _, current: 0 } } } diff --git a/font/src/ft/fc/mod.rs b/font/src/ft/fc/mod.rs index 5e5deb0..ae8fb80 100644 --- a/font/src/ft/fc/mod.rs +++ b/font/src/ft/fc/mod.rs @@ -12,21 +12,21 @@ // See the License for the specific language governing permissions and // limitations under the License. // -use std::ptr; use std::fmt; +use std::ptr; use foreign_types::{ForeignType, ForeignTypeRef}; use fontconfig::fontconfig as ffi; -use self::ffi::{FcSetSystem, FcSetApplication}; use self::ffi::FcResultNoMatch; -use self::ffi::{FcFontMatch, FcFontList, FcFontSort}; +use self::ffi::{FcFontList, FcFontMatch, FcFontSort}; use self::ffi::{FcMatchFont, FcMatchPattern, FcMatchScan}; -use self::ffi::{FC_SLANT_OBLIQUE, FC_SLANT_ITALIC, FC_SLANT_ROMAN}; -use self::ffi::{FC_WEIGHT_THIN, FC_WEIGHT_EXTRALIGHT, FC_WEIGHT_LIGHT}; -use self::ffi::{FC_WEIGHT_BOOK, FC_WEIGHT_REGULAR, FC_WEIGHT_MEDIUM, FC_WEIGHT_SEMIBOLD}; -use self::ffi::{FC_WEIGHT_BOLD, FC_WEIGHT_EXTRABOLD, FC_WEIGHT_BLACK, FC_WEIGHT_EXTRABLACK}; +use self::ffi::{FcSetApplication, FcSetSystem}; +use self::ffi::{FC_SLANT_ITALIC, FC_SLANT_OBLIQUE, FC_SLANT_ROMAN}; +use self::ffi::{FC_WEIGHT_BLACK, FC_WEIGHT_BOLD, FC_WEIGHT_EXTRABLACK, FC_WEIGHT_EXTRABOLD}; +use self::ffi::{FC_WEIGHT_BOOK, FC_WEIGHT_MEDIUM, FC_WEIGHT_REGULAR, FC_WEIGHT_SEMIBOLD}; +use self::ffi::{FC_WEIGHT_EXTRALIGHT, FC_WEIGHT_LIGHT, FC_WEIGHT_THIN}; pub mod config; pub use self::config::{Config, ConfigRef}; @@ -46,10 +46,7 @@ pub use self::pattern::{Pattern, PatternRef}; /// Find the font closest matching the provided pattern. /// /// The returned pattern is the result of Pattern::render_prepare. -pub fn font_match( - config: &ConfigRef, - pattern: &mut PatternRef, -) -> Option { +pub fn font_match(config: &ConfigRef, pattern: &mut PatternRef) -> Option { pattern.config_substitute(config, MatchKind::Pattern); pattern.default_substitute(); @@ -57,11 +54,7 @@ pub fn font_match( // What is this result actually used for? Seems redundant with // return type. let mut result = FcResultNoMatch; - let ptr = FcFontMatch( - config.as_ptr(), - pattern.as_ptr(), - &mut result, - ); + let ptr = FcFontMatch(config.as_ptr(), pattern.as_ptr(), &mut result); if ptr.is_null() { None @@ -72,10 +65,7 @@ pub fn font_match( } /// list fonts by closeness to the pattern -pub fn font_sort( - config: &ConfigRef, - pattern: &mut PatternRef, -) -> Option { +pub fn font_sort(config: &ConfigRef, pattern: &mut PatternRef) -> Option { pattern.config_substitute(config, MatchKind::Pattern); pattern.default_substitute(); @@ -112,11 +102,7 @@ pub fn font_list( pattern.default_substitute(); unsafe { - let ptr = FcFontList( - config.as_ptr(), - pattern.as_ptr(), - objects.as_ptr(), - ); + let ptr = FcFontList(config.as_ptr(), pattern.as_ptr(), objects.as_ptr()); if ptr.is_null() { None @@ -174,7 +160,7 @@ pub enum Width { Expanded, Extraexpanded, Ultraexpanded, - Other(i32) + Other(i32), } impl Width { @@ -190,7 +176,7 @@ impl Width { Expanded => 125, Extraexpanded => 150, Ultraexpanded => 200, - Other(value) => value as isize + Other(value) => value as isize, } } } @@ -207,7 +193,7 @@ impl From for Width { 125 => Width::Expanded, 150 => Width::Extraexpanded, 200 => Width::Ultraexpanded, - _ => Width::Other(value as _) + _ => Width::Other(value as _), } } } @@ -219,7 +205,7 @@ pub enum Rgba { Bgr, Vrgb, Vbgr, - None + None, } impl Rgba { @@ -230,7 +216,7 @@ impl Rgba { Rgba::Bgr => 2, Rgba::Vrgb => 3, Rgba::Vbgr => 4, - Rgba::None => 5 + Rgba::None => 5, } } } @@ -268,7 +254,7 @@ pub enum HintStyle { None, Slight, Medium, - Full + Full, } impl fmt::Display for HintStyle { @@ -287,7 +273,7 @@ pub enum LcdFilter { None, Default, Light, - Legacy + Legacy, } impl fmt::Display for LcdFilter { @@ -334,8 +320,7 @@ mod tests { pattern.set_slant(Slant::Italic); let config = Config::get_current(); - let fonts = super::font_sort(config, &mut pattern) - .expect("sort font monospace"); + let fonts = super::font_sort(config, &mut pattern).expect("sort font monospace"); for font in fonts.into_iter().take(10) { let font = font.render_prepare(&config, &pattern); diff --git a/font/src/ft/fc/object_set.rs b/font/src/ft/fc/object_set.rs index 47d1167..2494b58 100644 --- a/font/src/ft/fc/object_set.rs +++ b/font/src/ft/fc/object_set.rs @@ -13,8 +13,8 @@ // limitations under the License. use libc::c_char; +use super::ffi::{FcObjectSet, FcObjectSetAdd, FcObjectSetCreate, FcObjectSetDestroy}; use foreign_types::ForeignTypeRef; -use super::ffi::{FcObjectSetCreate, FcObjectSetAdd, FcObjectSet, FcObjectSetDestroy}; foreign_type! { type CType = FcObjectSet; @@ -31,9 +31,7 @@ impl ObjectSet { impl Default for ObjectSet { fn default() -> Self { - ObjectSet(unsafe { - FcObjectSetCreate() - }) + ObjectSet(unsafe { FcObjectSetCreate() }) } } diff --git a/font/src/ft/fc/pattern.rs b/font/src/ft/fc/pattern.rs index bb0c4c3..84187aa 100644 --- a/font/src/ft/fc/pattern.rs +++ b/font/src/ft/fc/pattern.rs @@ -11,38 +11,34 @@ // 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::ptr; -use std::fmt; use std::ffi::{CStr, CString}; -use std::path::PathBuf; -use std::str; +use std::fmt; use std::mem; +use std::path::PathBuf; +use std::ptr; +use std::str; -use libc::{c_char, c_int, c_double}; use foreign_types::{ForeignType, ForeignTypeRef}; +use libc::{c_char, c_double, c_int}; use super::ffi::FcResultMatch; -use super::ffi::{FcPatternDestroy, FcPatternAddCharSet}; -use super::ffi::{FcPatternGetString, FcPatternCreate, FcPatternAddString, FcPatternAddDouble}; -use super::ffi::{FcPatternGetInteger, FcPatternAddInteger, FcPatternPrint}; -use super::ffi::{FcChar8, FcPattern, FcDefaultSubstitute, FcConfigSubstitute}; -use super::ffi::{FcFontRenderPrepare, FcPatternGetBool, FcBool, FcPatternGetDouble}; +use super::ffi::{FcBool, FcFontRenderPrepare, FcPatternGetBool, FcPatternGetDouble}; +use super::ffi::{FcChar8, FcConfigSubstitute, FcDefaultSubstitute, FcPattern}; +use super::ffi::{FcPatternAddCharSet, FcPatternDestroy}; +use super::ffi::{FcPatternAddDouble, FcPatternAddString, FcPatternCreate, FcPatternGetString}; +use super::ffi::{FcPatternAddInteger, FcPatternGetInteger, FcPatternPrint}; -use super::{MatchKind, ConfigRef, CharSetRef, Weight, Slant, Width, Rgba, HintStyle, LcdFilter}; +use super::{CharSetRef, ConfigRef, HintStyle, LcdFilter, MatchKind, Rgba, Slant, Weight, Width}; pub struct StringPropertyIter<'a> { pattern: &'a PatternRef, object: &'a [u8], - index: usize + index: usize, } impl<'a> StringPropertyIter<'a> { fn new<'b>(pattern: &'b PatternRef, object: &'b [u8]) -> StringPropertyIter<'b> { - StringPropertyIter { - pattern, - object, - index: 0 - } + StringPropertyIter { pattern, object, index: 0 } } fn get_value(&self, index: usize) -> Option<&'a str> { @@ -53,7 +49,7 @@ impl<'a> StringPropertyIter<'a> { self.pattern.as_ptr(), self.object.as_ptr() as *mut c_char, index as c_int, - &mut value + &mut value, ) }; @@ -75,17 +71,12 @@ impl<'a> StringPropertyIter<'a> { pub struct BooleanPropertyIter<'a> { pattern: &'a PatternRef, object: &'a [u8], - index: usize + index: usize, } - impl<'a> BooleanPropertyIter<'a> { fn new<'b>(pattern: &'b PatternRef, object: &'b [u8]) -> BooleanPropertyIter<'b> { - BooleanPropertyIter { - pattern, - object, - index: 0 - } + BooleanPropertyIter { pattern, object, index: 0 } } fn get_value(&self, index: usize) -> Option { @@ -96,7 +87,7 @@ impl<'a> BooleanPropertyIter<'a> { self.pattern.as_ptr(), self.object.as_ptr() as *mut c_char, index as c_int, - &mut value + &mut value, ) }; @@ -112,16 +103,12 @@ impl<'a> BooleanPropertyIter<'a> { pub struct IntPropertyIter<'a> { pattern: &'a PatternRef, object: &'a [u8], - index: usize + index: usize, } impl<'a> IntPropertyIter<'a> { fn new<'b>(pattern: &'b PatternRef, object: &'b [u8]) -> IntPropertyIter<'b> { - IntPropertyIter { - pattern, - object, - index: 0 - } + IntPropertyIter { pattern, object, index: 0 } } fn get_value(&self, index: usize) -> Option { @@ -132,7 +119,7 @@ impl<'a> IntPropertyIter<'a> { self.pattern.as_ptr(), self.object.as_ptr() as *mut c_char, index as c_int, - &mut value + &mut value, ) }; @@ -150,9 +137,7 @@ pub struct RgbaPropertyIter<'a> { impl<'a> RgbaPropertyIter<'a> { fn new<'b>(pattern: &'b PatternRef, object: &'b [u8]) -> RgbaPropertyIter<'b> { - RgbaPropertyIter { - inner: IntPropertyIter::new(pattern, object) - } + RgbaPropertyIter { inner: IntPropertyIter::new(pattern, object) } } #[inline] @@ -161,8 +146,7 @@ impl<'a> RgbaPropertyIter<'a> { } fn get_value(&self, index: usize) -> Option { - self.inner.get_value(index) - .map(Rgba::from) + self.inner.get_value(index).map(Rgba::from) } } @@ -172,9 +156,7 @@ pub struct HintStylePropertyIter<'a> { impl<'a> HintStylePropertyIter<'a> { fn new(pattern: &PatternRef) -> HintStylePropertyIter { - HintStylePropertyIter { - inner: IntPropertyIter::new(pattern, b"hintstyle\0") - } + HintStylePropertyIter { inner: IntPropertyIter::new(pattern, b"hintstyle\0") } } #[inline] @@ -183,16 +165,15 @@ impl<'a> HintStylePropertyIter<'a> { } fn get_value(&self, index: usize) -> Option { - self.inner.get_value(index) - .and_then(|hint_style| { - Some(match hint_style { - 0 => HintStyle::None, - 1 => HintStyle::Slight, - 2 => HintStyle::Medium, - 3 => HintStyle::Full, - _ => return None - }) + self.inner.get_value(index).and_then(|hint_style| { + Some(match hint_style { + 0 => HintStyle::None, + 1 => HintStyle::Slight, + 2 => HintStyle::Medium, + 3 => HintStyle::Full, + _ => return None, }) + }) } } @@ -202,9 +183,7 @@ pub struct LcdFilterPropertyIter<'a> { impl<'a> LcdFilterPropertyIter<'a> { fn new(pattern: &PatternRef) -> LcdFilterPropertyIter { - LcdFilterPropertyIter { - inner: IntPropertyIter::new(pattern, b"lcdfilter\0") - } + LcdFilterPropertyIter { inner: IntPropertyIter::new(pattern, b"lcdfilter\0") } } #[inline] @@ -213,16 +192,15 @@ impl<'a> LcdFilterPropertyIter<'a> { } fn get_value(&self, index: usize) -> Option { - self.inner.get_value(index) - .and_then(|hint_style| { - Some(match hint_style { - 0 => LcdFilter::None, - 1 => LcdFilter::Default, - 2 => LcdFilter::Light, - 3 => LcdFilter::Legacy, - _ => return None - }) + self.inner.get_value(index).and_then(|hint_style| { + Some(match hint_style { + 0 => LcdFilter::None, + 1 => LcdFilter::Default, + 2 => LcdFilter::Light, + 3 => LcdFilter::Legacy, + _ => return None, }) + }) } } @@ -230,16 +208,12 @@ impl<'a> LcdFilterPropertyIter<'a> { pub struct DoublePropertyIter<'a> { pattern: &'a PatternRef, object: &'a [u8], - index: usize + index: usize, } impl<'a> DoublePropertyIter<'a> { fn new<'b>(pattern: &'b PatternRef, object: &'b [u8]) -> DoublePropertyIter<'b> { - DoublePropertyIter { - pattern, - object, - index: 0 - } + DoublePropertyIter { pattern, object, index: 0 } } fn get_value(&self, index: usize) -> Option { @@ -250,7 +224,7 @@ impl<'a> DoublePropertyIter<'a> { self.pattern.as_ptr(), self.object.as_ptr() as *mut c_char, index as c_int, - &mut value + &mut value, ) }; @@ -277,13 +251,13 @@ macro_rules! impl_property_iter_debug { write!(f, "{}", val)?; } }, - _ => break + _ => break, } } write!(f, "]") } } - } + }; } /// Implement Iterator and Debug for a property iterator @@ -427,76 +401,6 @@ macro_rules! double_getter { } impl PatternRef { - // Prints the pattern to stdout - // - // FontConfig doesn't expose a way to iterate over all members of a pattern; - // instead, we just defer to FcPatternPrint. Otherwise, this could have been - // a `fmt::Debug` impl. - pub fn print(&self) { - unsafe { - FcPatternPrint(self.as_ptr()) - } - } - - /// Add a string value to the pattern - /// - /// If the returned value is `true`, the value is added at the end of - /// any existing list, otherwise it is inserted at the beginning. - /// - /// # Unsafety - /// - /// `object` is not checked to be a valid null-terminated string - unsafe fn add_string(&mut self, object: &[u8], value: &str) -> bool { - let value = CString::new(&value[..]).unwrap(); - let value = value.as_ptr(); - - FcPatternAddString( - self.as_ptr(), - object.as_ptr() as *mut c_char, - value as *mut FcChar8 - ) == 1 - } - - unsafe fn add_integer(&self, object: &[u8], int: isize) -> bool { - FcPatternAddInteger( - self.as_ptr(), - object.as_ptr() as *mut c_char, - int as c_int - ) == 1 - } - - unsafe fn add_double(&self, object: &[u8], value: f64) -> bool { - FcPatternAddDouble( - self.as_ptr(), - object.as_ptr() as *mut c_char, - value as c_double - ) == 1 - } - - unsafe fn get_string<'a>(&'a self, object: &'a [u8]) -> StringPropertyIter<'a> { - StringPropertyIter::new(self, object) - } - - unsafe fn get_integer<'a>(&'a self, object: &'a [u8]) -> IntPropertyIter<'a> { - IntPropertyIter::new(self, object) - } - - unsafe fn get_double<'a>(&'a self, object: &'a [u8]) -> DoublePropertyIter<'a> { - DoublePropertyIter::new(self, object) - } - - unsafe fn get_boolean<'a>(&'a self, object: &'a [u8]) -> BooleanPropertyIter<'a> { - BooleanPropertyIter::new(self, object) - } - - pub fn hintstyle(&self) -> HintStylePropertyIter { - HintStylePropertyIter::new(self) - } - - pub fn lcdfilter(&self) -> LcdFilterPropertyIter { - LcdFilterPropertyIter::new(self) - } - boolean_getter! { antialias() => b"antialias\0", hinting() => b"hinting\0", @@ -535,36 +439,85 @@ impl PatternRef { [postscriptname, add_postscriptname] => b"postscriptname\0" } + pattern_get_integer! { + index() => b"index\0" + } + + // Prints the pattern to stdout + // + // FontConfig doesn't expose a way to iterate over all members of a pattern; + // instead, we just defer to FcPatternPrint. Otherwise, this could have been + // a `fmt::Debug` impl. + pub fn print(&self) { + unsafe { FcPatternPrint(self.as_ptr()) } + } + + /// Add a string value to the pattern + /// + /// If the returned value is `true`, the value is added at the end of + /// any existing list, otherwise it is inserted at the beginning. + /// + /// # Unsafety + /// + /// `object` is not checked to be a valid null-terminated string + unsafe fn add_string(&mut self, object: &[u8], value: &str) -> bool { + let value = CString::new(&value[..]).unwrap(); + let value = value.as_ptr(); + + FcPatternAddString(self.as_ptr(), object.as_ptr() as *mut c_char, value as *mut FcChar8) + == 1 + } + + unsafe fn add_integer(&self, object: &[u8], int: isize) -> bool { + FcPatternAddInteger(self.as_ptr(), object.as_ptr() as *mut c_char, int as c_int) == 1 + } + + unsafe fn add_double(&self, object: &[u8], value: f64) -> bool { + FcPatternAddDouble(self.as_ptr(), object.as_ptr() as *mut c_char, value as c_double) == 1 + } + + unsafe fn get_string<'a>(&'a self, object: &'a [u8]) -> StringPropertyIter<'a> { + StringPropertyIter::new(self, object) + } + + unsafe fn get_integer<'a>(&'a self, object: &'a [u8]) -> IntPropertyIter<'a> { + IntPropertyIter::new(self, object) + } + + unsafe fn get_double<'a>(&'a self, object: &'a [u8]) -> DoublePropertyIter<'a> { + DoublePropertyIter::new(self, object) + } + + unsafe fn get_boolean<'a>(&'a self, object: &'a [u8]) -> BooleanPropertyIter<'a> { + BooleanPropertyIter::new(self, object) + } + + pub fn hintstyle(&self) -> HintStylePropertyIter { + HintStylePropertyIter::new(self) + } + + pub fn lcdfilter(&self) -> LcdFilterPropertyIter { + LcdFilterPropertyIter::new(self) + } + pub fn set_slant(&mut self, slant: Slant) -> bool { - unsafe { - self.add_integer(b"slant\0", slant as isize) - } + unsafe { self.add_integer(b"slant\0", slant as isize) } } pub fn add_pixelsize(&mut self, size: f64) -> bool { - unsafe { - self.add_double(b"pixelsize\0", size) - } + unsafe { self.add_double(b"pixelsize\0", size) } } pub fn set_weight(&mut self, weight: Weight) -> bool { - unsafe { - self.add_integer(b"weight\0", weight as isize) - } + unsafe { self.add_integer(b"weight\0", weight as isize) } } pub fn set_width(&mut self, width: Width) -> bool { - unsafe { - self.add_integer(b"width\0", width.to_isize()) - } + unsafe { self.add_integer(b"width\0", width.to_isize()) } } pub fn get_width(&self) -> Option { - unsafe { - self.get_integer(b"width\0") - .nth(0) - .map(Width::from) - } + unsafe { self.get_integer(b"width\0").nth(0).map(Width::from) } } pub fn rgba(&self) -> RgbaPropertyIter { @@ -572,9 +525,7 @@ impl PatternRef { } pub fn set_rgba(&self, rgba: &Rgba) -> bool { - unsafe { - self.add_integer(b"rgba\0", rgba.to_isize()) - } + unsafe { self.add_integer(b"rgba\0", rgba.to_isize()) } } pub fn render_prepare(&self, config: &ConfigRef, request: &PatternRef) -> Pattern { @@ -595,19 +546,13 @@ impl PatternRef { FcPatternAddCharSet( self.as_ptr(), b"charset\0".as_ptr() as *mut c_char, - charset.as_ptr() + charset.as_ptr(), ) == 1 } } pub fn file(&self, index: usize) -> Option { - unsafe { - self.get_string(b"file\0").nth(index) - }.map(From::from) - } - - pattern_get_integer! { - index() => b"index\0" + unsafe { self.get_string(b"file\0").nth(index) }.map(From::from) } pub fn config_substitute(&mut self, config: &ConfigRef, kind: MatchKind) { @@ -622,4 +567,3 @@ impl PatternRef { } } } - diff --git a/font/src/ft/mod.rs b/font/src/ft/mod.rs index 6bcda2a..bc6d6d8 100644 --- a/font/src/ft/mod.rs +++ b/font/src/ft/mod.rs @@ -13,19 +13,18 @@ // limitations under the License. // //! Rasterization powered by FreeType and FontConfig -use std::collections::HashMap; use std::cmp::min; -use std::path::PathBuf; +use std::collections::HashMap; use std::fmt; +use std::path::PathBuf; use freetype::tt_os2::TrueTypeOS2Table; use freetype::{self, Library}; use libc::c_uint; - pub mod fc; -use super::{FontDesc, RasterizedGlyph, Metrics, Size, FontKey, GlyphKey, Weight, Slant, Style}; +use super::{FontDesc, FontKey, GlyphKey, Metrics, RasterizedGlyph, Size, Slant, Style, Weight}; struct FixedSize { pixelsize: f64, @@ -37,7 +36,7 @@ struct Face { load_flags: freetype::face::LoadFlag, render_mode: freetype::RenderMode, lcd_filter: c_uint, - non_scalable: Option + non_scalable: Option, } impl fmt::Debug for Face { @@ -46,14 +45,17 @@ impl fmt::Debug for Face { .field("ft_face", &self.ft_face) .field("key", &self.key) .field("load_flags", &self.load_flags) - .field("render_mode", &match self.render_mode { - freetype::RenderMode::Normal => "Normal", - freetype::RenderMode::Light => "Light", - freetype::RenderMode::Mono => "Mono", - freetype::RenderMode::Lcd => "Lcd", - freetype::RenderMode::LcdV => "LcdV", - freetype::RenderMode::Max => "Max", - }) + .field( + "render_mode", + &match self.render_mode { + freetype::RenderMode::Normal => "Normal", + freetype::RenderMode::Light => "Light", + freetype::RenderMode::Mono => "Mono", + freetype::RenderMode::Lcd => "Lcd", + freetype::RenderMode::LcdV => "LcdV", + freetype::RenderMode::Max => "Max", + }, + ) .field("lcd_filter", &self.lcd_filter) .finish() } @@ -87,9 +89,7 @@ impl ::Rasterize for FreeTypeRasterizer { } fn metrics(&self, key: FontKey, _size: Size) -> Result { - let face = self.faces - .get(&key) - .ok_or(Error::FontNotLoaded)?; + let face = self.faces.get(&key).ok_or(Error::FontNotLoaded)?; let full = self.full_metrics(key)?; let height = (full.size_metrics.height / 64) as f64; @@ -108,20 +108,19 @@ impl ::Rasterize for FreeTypeRasterizer { // Get strikeout position and thickness in device pixels let (strikeout_position, strikeout_thickness) = - match TrueTypeOS2Table::from_face(&mut face.ft_face.clone()) - { - Some(os2) => { - let strikeout_position = f32::from(os2.y_strikeout_position()) * x_scale / 64.; - let strikeout_thickness = f32::from(os2.y_strikeout_size()) * x_scale / 64.; - (strikeout_position, strikeout_thickness) - }, - _ => { - // Fallback if font doesn't provide info about strikeout - trace!("Using fallback strikeout metrics"); - let strikeout_position = height as f32 / 2. + descent; - (strikeout_position, underline_thickness) - }, - }; + match TrueTypeOS2Table::from_face(&mut face.ft_face.clone()) { + Some(os2) => { + let strikeout_position = f32::from(os2.y_strikeout_position()) * x_scale / 64.; + let strikeout_thickness = f32::from(os2.y_strikeout_size()) * x_scale / 64.; + (strikeout_position, strikeout_thickness) + }, + _ => { + // Fallback if font doesn't provide info about strikeout + trace!("Using fallback strikeout metrics"); + let strikeout_position = height as f32 / 2. + descent; + (strikeout_position, underline_thickness) + }, + }; Ok(Metrics { average_advance: full.cell_width, @@ -154,6 +153,7 @@ pub trait IntoFontconfigType { impl IntoFontconfigType for Slant { type FcType = fc::Slant; + fn into_fontconfig_type(&self) -> Self::FcType { match *self { Slant::Normal => fc::Slant::Roman, @@ -176,7 +176,7 @@ impl IntoFontconfigType for Weight { struct FullMetrics { size_metrics: freetype::ffi::FT_Size_Metrics, - cell_width: f64 + cell_width: f64, } impl FreeTypeRasterizer { @@ -189,31 +189,25 @@ impl FreeTypeRasterizer { Style::Description { slant, weight } => { // Match nearest font self.get_matching_face(&desc, slant, weight, size) - } + }, Style::Specific(ref style) => { // If a name was specified, try and load specifically that font. self.get_specific_face(&desc, &style, size) - } + }, } } fn full_metrics(&self, key: FontKey) -> Result { - let face = self.faces - .get(&key) - .ok_or(Error::FontNotLoaded)?; + let face = self.faces.get(&key).ok_or(Error::FontNotLoaded)?; - let size_metrics = face.ft_face.size_metrics() - .ok_or(Error::MissingSizeMetrics)?; + let size_metrics = face.ft_face.size_metrics().ok_or(Error::MissingSizeMetrics)?; let width = match face.ft_face.load_char('0' as usize, face.load_flags) { - Ok(_) => face.ft_face.glyph().metrics().horiAdvance / 64, - Err(_) => size_metrics.max_advance / 64 + Ok(_) => face.ft_face.glyph().metrics().horiAdvance / 64, + Err(_) => size_metrics.max_advance / 64, } as f64; - Ok(FullMetrics { - size_metrics, - cell_width: width - }) + Ok(FullMetrics { size_metrics, cell_width: width }) } fn get_matching_face( @@ -232,12 +226,9 @@ impl FreeTypeRasterizer { let font = fc::font_match(fc::Config::get_current(), &mut pattern) .ok_or_else(|| Error::MissingFont(desc.to_owned()))?; - self.face_from_pattern(&font) - .and_then(|pattern| { - pattern - .map(Ok) - .unwrap_or_else(|| Err(Error::MissingFont(desc.to_owned()))) - }) + self.face_from_pattern(&font).and_then(|pattern| { + pattern.map(Ok).unwrap_or_else(|| Err(Error::MissingFont(desc.to_owned()))) + }) } fn get_specific_face( @@ -253,12 +244,9 @@ impl FreeTypeRasterizer { let font = fc::font_match(fc::Config::get_current(), &mut pattern) .ok_or_else(|| Error::MissingFont(desc.to_owned()))?; - self.face_from_pattern(&font) - .and_then(|pattern| { - pattern - .map(Ok) - .unwrap_or_else(|| Err(Error::MissingFont(desc.to_owned()))) - }) + self.face_from_pattern(&font).and_then(|pattern| { + pattern.map(Ok).unwrap_or_else(|| Err(Error::MissingFont(desc.to_owned()))) + }) } fn face_from_pattern(&mut self, pattern: &fc::Pattern) -> Result, Error> { @@ -277,9 +265,7 @@ impl FreeTypeRasterizer { let mut pixelsize = pattern.pixelsize(); debug!("pixelsizes: {:?}", pixelsize); - Some(FixedSize { - pixelsize: pixelsize.next().expect("has 1+ pixelsize"), - }) + Some(FixedSize { pixelsize: pixelsize.next().expect("has 1+ pixelsize") }) }; let face = Face { @@ -303,7 +289,11 @@ impl FreeTypeRasterizer { } } - fn face_for_glyph(&mut self, glyph_key: GlyphKey, have_recursed: bool) -> Result { + fn face_for_glyph( + &mut self, + glyph_key: GlyphKey, + have_recursed: bool, + ) -> Result { let c = glyph_key.c; let use_initial_face = if let Some(face) = self.faces.get(&glyph_key.font_key) { @@ -322,8 +312,7 @@ impl FreeTypeRasterizer { } } - fn get_rendered_glyph(&mut self, glyph_key: GlyphKey) - -> Result { + fn get_rendered_glyph(&mut self, glyph_key: GlyphKey) -> Result { // Render a custom symbol for the underline and beam cursor match glyph_key.c { super::UNDERLINE_CURSOR_CHAR => { @@ -370,9 +359,10 @@ impl FreeTypeRasterizer { let face = &self.faces[&font_key]; let index = face.ft_face.get_char_index(glyph_key.c as usize); - let size = face.non_scalable.as_ref() - .map(|v| v.pixelsize as f32) - .unwrap_or_else(|| glyph_key.size.as_f32_pts() * self.device_pixel_ratio * 96. / 72.); + let size = + face.non_scalable.as_ref().map(|v| v.pixelsize as f32).unwrap_or_else(|| { + glyph_key.size.as_f32_pts() * self.device_pixel_ratio * 96. / 72. + }); face.ft_face.set_char_size(to_freetype_26_6(size), 0, 0, 0)?; @@ -405,7 +395,7 @@ impl FreeTypeRasterizer { use freetype::face::LoadFlag; match (antialias, hinting, rgba) { (false, fc::HintStyle::None, _) => LoadFlag::NO_HINTING | LoadFlag::MONOCHROME, - (false, _, _) => LoadFlag::TARGET_MONO | LoadFlag::MONOCHROME, + (false, ..) => LoadFlag::TARGET_MONO | LoadFlag::MONOCHROME, (true, fc::HintStyle::None, _) => LoadFlag::NO_HINTING | LoadFlag::TARGET_NORMAL, // hintslight does *not* use LCD hinting even when a subpixel mode // is selected. @@ -459,7 +449,9 @@ impl FreeTypeRasterizer { /// Given a FreeType `Bitmap`, returns packed buffer with 1 byte per LCD channel. /// /// The i32 value in the return type is the number of pixels per row. - fn normalize_buffer(bitmap: &freetype::bitmap::Bitmap) -> freetype::FtResult<(i32, i32, Vec)> { + fn normalize_buffer( + bitmap: &freetype::bitmap::Bitmap, + ) -> freetype::FtResult<(i32, i32, Vec)> { use freetype::bitmap::PixelMode; let buf = bitmap.buffer(); @@ -475,7 +467,7 @@ impl FreeTypeRasterizer { Ok((bitmap.rows(), bitmap.width() / 3, packed)) }, PixelMode::LcdV => { - for i in 0..bitmap.rows()/3 { + for i in 0..bitmap.rows() / 3 { for j in 0..bitmap.width() { for k in 0..3 { let offset = ((i as usize) * 3 + k) * pitch + (j as usize); @@ -529,14 +521,11 @@ impl FreeTypeRasterizer { } Ok((bitmap.rows(), bitmap.width(), packed)) }, - mode => panic!("unhandled pixel mode: {:?}", mode) + mode => panic!("unhandled pixel mode: {:?}", mode), } } - fn load_face_with_glyph( - &mut self, - glyph: char, - ) -> Result { + fn load_face_with_glyph(&mut self, glyph: char) -> Result { let mut charset = fc::CharSet::new(); charset.add(glyph); let mut pattern = fc::Pattern::new(); @@ -560,19 +549,19 @@ impl FreeTypeRasterizer { // and index above. let key = self.face_from_pattern(&pattern)?.unwrap(); Ok(key) - } + }, } - } - else { - Err(Error::MissingFont( - FontDesc::new("fallback-without-path", Style::Specific(glyph.to_string())))) + } else { + Err(Error::MissingFont(FontDesc::new( + "fallback-without-path", + Style::Specific(glyph.to_string()), + ))) } }, - None => { - Err(Error::MissingFont( - FontDesc::new("no-fallback-for", Style::Specific(glyph.to_string())) - )) - } + None => Err(Error::MissingFont(FontDesc::new( + "no-fallback-for", + Style::Specific(glyph.to_string()), + ))), } } } @@ -614,19 +603,17 @@ impl ::std::error::Error for Error { impl ::std::fmt::Display for Error { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { match *self { - Error::FreeType(ref err) => { - err.fmt(f) - }, - Error::MissingFont(ref desc) => { - write!(f, "Couldn't find a font with {}\ - \n\tPlease check the font config in your alacritty.yml.", desc) - }, - Error::FontNotLoaded => { - f.write_str("Tried to use a font that hasn't been loaded") - }, + Error::FreeType(ref err) => err.fmt(f), + Error::MissingFont(ref desc) => write!( + f, + "Couldn't find a font with {}\n\tPlease check the font config in your \ + alacritty.yml.", + desc + ), + Error::FontNotLoaded => f.write_str("Tried to use a font that hasn't been loaded"), Error::MissingSizeMetrics => { f.write_str("Tried to get size metrics from a face without a size") - } + }, } } } diff --git a/font/src/lib.rs b/font/src/lib.rs index 8762c0b..f23d0a0 100644 --- a/font/src/lib.rs +++ b/font/src/lib.rs @@ -46,8 +46,8 @@ extern crate foreign_types; extern crate log; use std::hash::{Hash, Hasher}; -use std::{fmt, cmp}; use std::sync::atomic::{AtomicUsize, Ordering}; +use std::{cmp, fmt}; // If target isn't macos or windows, reexport everything from ft #[cfg(not(any(target_os = "macos", windows)))] @@ -113,7 +113,7 @@ impl fmt::Display for Style { Style::Specific(ref s) => f.write_str(&s), Style::Description { slant, weight } => { write!(f, "slant={:?}, weight={:?}", slant, weight) - } + }, } } } @@ -123,10 +123,7 @@ impl FontDesc { where S: Into, { - FontDesc { - name: name.into(), - style, - } + FontDesc { name: name.into(), style } } } @@ -149,9 +146,7 @@ impl FontKey { pub fn next() -> FontKey { static TOKEN: AtomicUsize = AtomicUsize::new(0); - FontKey { - token: TOKEN.fetch_add(1, Ordering::SeqCst) as _, - } + FontKey { token: TOKEN.fetch_add(1, Ordering::SeqCst) as _ } } } @@ -170,7 +165,8 @@ impl Hash for GlyphKey { // - If GlyphKey ever becomes a different size, this will fail to compile // - Result is being used for hashing and has no fields (it's a u64) ::std::mem::transmute::(*self) - }.hash(state); + } + .hash(state); } } @@ -228,14 +224,7 @@ pub struct RasterizedGlyph { impl Default for RasterizedGlyph { fn default() -> RasterizedGlyph { - RasterizedGlyph { - c: ' ', - width: 0, - height: 0, - top: 0, - left: 0, - buf: Vec::new(), - } + RasterizedGlyph { c: ' ', width: 0, height: 0, top: 0, left: 0, buf: Vec::new() } } } @@ -288,8 +277,11 @@ pub fn get_box_cursor_glyph( let mut buf = Vec::with_capacity((width * height * 3) as usize); for y in 0..height { for x in 0..width { - if y < border_width || y >= height - border_width || - x < border_width || x >= width - border_width { + if y < border_width + || y >= height - border_width + || x < border_width + || x >= width - border_width + { buf.append(&mut vec![255u8; 3]); } else { buf.append(&mut vec![0u8; 3]); @@ -298,24 +290,14 @@ pub fn get_box_cursor_glyph( } // Create a custom glyph with the rectangle data attached to it - Ok(RasterizedGlyph { - c: BOX_CURSOR_CHAR, - top: ascent, - left: 0, - height, - width, - buf, - }) + Ok(RasterizedGlyph { c: BOX_CURSOR_CHAR, top: ascent, left: 0, height, width, buf }) } struct BufDebugger<'a>(&'a [u8]); impl<'a> fmt::Debug for BufDebugger<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("GlyphBuffer") - .field("len", &self.0.len()) - .field("bytes", &self.0) - .finish() + f.debug_struct("GlyphBuffer").field("len", &self.0.len()).field("bytes", &self.0).finish() } } diff --git a/font/src/rusttype/mod.rs b/font/src/rusttype/mod.rs index e8e0bd2..be39ecc 100644 --- a/font/src/rusttype/mod.rs +++ b/font/src/rusttype/mod.rs @@ -15,10 +15,7 @@ impl crate::Rasterize for RustTypeRasterizer { type Err = Error; fn new(device_pixel_ratio: f32, _: bool) -> Result { - Ok(RustTypeRasterizer { - fonts: Vec::new(), - dpi_ratio: device_pixel_ratio, - }) + Ok(RustTypeRasterizer { fonts: Vec::new(), dpi_ratio: device_pixel_ratio }) } fn metrics(&self, key: FontKey, size: Size) -> Result { @@ -56,17 +53,13 @@ impl crate::Rasterize for RustTypeRasterizer { } fn load_font(&mut self, desc: &FontDesc, _size: Size) -> Result { - let fp = system_fonts::FontPropertyBuilder::new() - .family(&desc.name) - .monospace(); + let fp = system_fonts::FontPropertyBuilder::new().family(&desc.name).monospace(); let fp = match desc.style { - Style::Specific(ref style) => { - match style.to_lowercase().as_str() { - "italic" => fp.italic(), - "bold" => fp.bold(), - _ => fp, - } + Style::Specific(ref style) => match style.to_lowercase().as_str() { + "italic" => fp.italic(), + "bold" => fp.bold(), + _ => fp, }, Style::Description { slant, weight } => { let fp = match slant { @@ -79,52 +72,52 @@ impl crate::Rasterize for RustTypeRasterizer { Weight::Bold => fp.bold(), Weight::Normal => fp, } - } + }, }; - self.fonts.push(FontCollection::from_bytes( - system_fonts::get(&fp.build()) - .ok_or_else(|| Error::MissingFont(desc.clone()))? - .0, - ).into_font() - .ok_or(Error::UnsupportedFont)?); - Ok(FontKey { - token: (self.fonts.len() - 1) as u16, - }) + self.fonts.push( + FontCollection::from_bytes( + system_fonts::get(&fp.build()).ok_or_else(|| Error::MissingFont(desc.clone()))?.0, + ) + .into_font() + .ok_or(Error::UnsupportedFont)?, + ); + Ok(FontKey { token: (self.fonts.len() - 1) as u16 }) } fn get_glyph(&mut self, glyph_key: GlyphKey) -> Result { match glyph_key.c { super::UNDERLINE_CURSOR_CHAR => { let metrics = self.metrics(glyph_key.font_key, glyph_key.size)?; - return super::get_underline_cursor_glyph(metrics.descent as i32, metrics.average_advance as i32); - } + return super::get_underline_cursor_glyph( + metrics.descent as i32, + metrics.average_advance as i32, + ); + }, super::BEAM_CURSOR_CHAR => { let metrics = self.metrics(glyph_key.font_key, glyph_key.size)?; return super::get_beam_cursor_glyph( (metrics.line_height + f64::from(metrics.descent)).round() as i32, metrics.line_height.round() as i32, - metrics.average_advance.round() as i32 + metrics.average_advance.round() as i32, ); - } + }, super::BOX_CURSOR_CHAR => { let metrics = self.metrics(glyph_key.font_key, glyph_key.size)?; return super::get_box_cursor_glyph( (metrics.line_height + f64::from(metrics.descent)).round() as i32, metrics.line_height.round() as i32, - metrics.average_advance.round() as i32 + metrics.average_advance.round() as i32, ); - } - _ => () + }, + _ => (), } let scaled_glyph = self.fonts[glyph_key.font_key.token as usize] .glyph(glyph_key.c) .ok_or(Error::MissingGlyph)? - .scaled(Scale::uniform( - glyph_key.size.as_f32_pts() * self.dpi_ratio * 96. / 72., - )); + .scaled(Scale::uniform(glyph_key.size.as_f32_pts() * self.dpi_ratio * 96. / 72.)); let glyph = scaled_glyph.positioned(point(0.0, 0.0)); @@ -132,10 +125,7 @@ impl crate::Rasterize for RustTypeRasterizer { let bb = match glyph.pixel_bounding_box() { Some(bb) => bb, // Bounding box calculation fails for spaces so we provide a placeholder bounding box - None => rusttype::Rect { - min: point(0, 0), - max: point(0, 0), - }, + None => rusttype::Rect { min: point(0, 0), max: point(0, 0) }, }; let mut buf = Vec::with_capacity((bb.width() * bb.height()) as usize); @@ -185,8 +175,8 @@ impl ::std::fmt::Display for Error { match *self { Error::MissingFont(ref desc) => write!( f, - "Couldn't find a font with {}\ - \n\tPlease check the font config in your alacritty.yml.", + "Couldn't find a font with {}\n\tPlease check the font config in your \ + alacritty.yml.", desc ), Error::UnsupportedFont => write!( @@ -195,7 +185,7 @@ impl ::std::fmt::Display for Error { ), Error::UnsupportedStyle => { write!(f, "The selected font style is not supported by rusttype.") - } + }, Error::MissingGlyph => write!(f, "The selected font did not have the requested glyph."), } } diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..bf8f13e --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,13 @@ +match_block_trailing_comma = true +condense_wildcard_suffixes = true +use_field_init_shorthand = true +overflow_delimited_expr = true +use_small_heuristics = "Max" +format_doc_comments = true +normalize_comments = true +reorder_impl_items = true +use_try_shorthand = true +newline_style = "Unix" +format_strings = true +wrap_comments = true +comment_width = 100 diff --git a/src/ansi.rs b/src/ansi.rs index dce83da..eb8764a 100644 --- a/src/ansi.rs +++ b/src/ansi.rs @@ -17,10 +17,10 @@ use std::io; use std::ops::Range; use std::str; -use vte; +use crate::index::{Column, Contains, Line}; use base64; use glutin::MouseCursor; -use crate::index::{Column, Line, Contains}; +use vte; use crate::term::color::Rgb; @@ -33,7 +33,7 @@ fn parse_rgb_color(color: &[u8]) -> Option { macro_rules! next { () => { iter.next().map(|v| *v as char) - } + }; } macro_rules! parse_hex { @@ -50,32 +50,36 @@ fn parse_rgb_color(color: &[u8]) -> Option { digit += value as u8; } digit - }} + }}; } match next!() { Some('r') => { - if next!() != Some('g') { return None; } - if next!() != Some('b') { return None; } - if next!() != Some(':') { return None; } + if next!() != Some('g') { + return None; + } + if next!() != Some('b') { + return None; + } + if next!() != Some(':') { + return None; + } let r = parse_hex!(); let val = next!(); - if val != Some('/') { return None; } + if val != Some('/') { + return None; + } let g = parse_hex!(); - if next!() != Some('/') { return None; } + if next!() != Some('/') { + return None; + } let b = parse_hex!(); Some(Rgb { r, g, b }) - } - Some('#') => { - Some(Rgb { - r: parse_hex!(), - g: parse_hex!(), - b: parse_hex!(), - }) - } - _ => None + }, + Some('#') => Some(Rgb { r: parse_hex!(), g: parse_hex!(), b: parse_hex!() }), + _ => None, } } @@ -106,7 +110,7 @@ pub struct Processor { /// Internal state for VTE processor struct ProcessorState { - preceding_char: Option + preceding_char: Option, } /// Helper type that implements `vte::Perform`. @@ -116,7 +120,7 @@ struct ProcessorState { struct Performer<'a, H: Handler + TermInfo, W: io::Write> { _state: &'a mut ProcessorState, handler: &'a mut H, - writer: &'a mut W + writer: &'a mut W, } impl<'a, H: Handler + TermInfo + 'a, W: io::Write> Performer<'a, H, W> { @@ -127,20 +131,13 @@ impl<'a, H: Handler + TermInfo + 'a, W: io::Write> Performer<'a, H, W> { handler: &'b mut H, writer: &'b mut W, ) -> Performer<'b, H, W> { - Performer { - _state: state, - handler, - writer, - } + Performer { _state: state, handler, writer } } } impl Default for Processor { fn default() -> Processor { - Processor { - state: ProcessorState { preceding_char: None }, - parser: vte::Parser::new(), - } + Processor { state: ProcessorState { preceding_char: None }, parser: vte::Parser::new() } } } @@ -150,21 +147,16 @@ impl Processor { } #[inline] - pub fn advance( - &mut self, - handler: &mut H, - byte: u8, - writer: &mut W - ) - where H: Handler + TermInfo, - W: io::Write + pub fn advance(&mut self, handler: &mut H, byte: u8, writer: &mut W) + where + H: Handler + TermInfo, + W: io::Write, { let mut performer = Performer::new(&mut self.state, handler, writer); self.parser.advance(&mut performer, byte); } } - /// Trait that provides properties of terminal pub trait TermInfo { fn lines(&self) -> Line; @@ -447,14 +439,14 @@ impl Mode { 2004 => Mode::BracketedPaste, _ => { trace!("[unimplemented] primitive mode: {}", num); - return None - } + return None; + }, }) } else { Some(match num { 4 => Mode::Insert, 20 => Mode::LineFeedNewLine, - _ => return None + _ => return None, }) } } @@ -485,7 +477,7 @@ pub enum ClearMode { /// Clear entire terminal All, /// Clear 'saved' lines (scrollback) - Saved + Saved, } /// Mode for clearing tab stops @@ -586,7 +578,7 @@ impl NamedColor { NamedColor::DimMagenta => NamedColor::Magenta, NamedColor::DimCyan => NamedColor::Cyan, NamedColor::DimWhite => NamedColor::White, - val => val + val => val, } } @@ -610,7 +602,7 @@ impl NamedColor { NamedColor::BrightCyan => NamedColor::Cyan, NamedColor::BrightWhite => NamedColor::White, NamedColor::BrightForeground => NamedColor::Foreground, - val => val + val => val, } } } @@ -697,8 +689,9 @@ impl Default for StandardCharset { } impl<'a, H, W> vte::Perform for Performer<'a, H, W> - where H: Handler + TermInfo + 'a, - W: io::Write + 'a +where + H: Handler + TermInfo + 'a, + W: io::Write + 'a, { #[inline] fn print(&mut self, c: char) { @@ -720,14 +713,16 @@ impl<'a, H, W> vte::Perform for Performer<'a, H, W> C1::NEL => self.handler.newline(), C1::HTS => self.handler.set_horizontal_tabstop(), C1::DECID => self.handler.identify_terminal(self.writer), - _ => debug!("[unhandled] execute byte={:02x}", byte) + _ => debug!("[unhandled] execute byte={:02x}", byte), } } #[inline] fn hook(&mut self, params: &[i64], intermediates: &[u8], ignore: bool) { - debug!("[unhandled hook] params={:?}, ints: {:?}, ignore: {:?}", - params, intermediates, ignore); + debug!( + "[unhandled hook] params={:?}, ints: {:?}, ignore: {:?}", + params, intermediates, ignore + ); } #[inline] @@ -788,7 +783,7 @@ impl<'a, H, W> vte::Perform for Performer<'a, H, W> } } unhandled(params); - } + }, // Set foreground color b"10" => { @@ -799,7 +794,7 @@ impl<'a, H, W> vte::Perform for Performer<'a, H, W> } } unhandled(params); - } + }, // Set background color b"11" => { @@ -810,7 +805,7 @@ impl<'a, H, W> vte::Perform for Performer<'a, H, W> } } unhandled(params); - } + }, // Set text cursor color b"12" => { @@ -821,11 +816,14 @@ impl<'a, H, W> vte::Perform for Performer<'a, H, W> } } unhandled(params); - } + }, // Set cursor style b"50" => { - if params.len() >= 2 && params[1].len() >= 13 && params[1][0..12] == *b"CursorShape=" { + if params.len() >= 2 + && params[1].len() >= 13 + && params[1][0..12] == *b"CursorShape=" + { let style = match params[1][12] as char { '0' => CursorStyle::Block, '1' => CursorStyle::Beam, @@ -836,7 +834,7 @@ impl<'a, H, W> vte::Perform for Performer<'a, H, W> return; } unhandled(params); - } + }, // Set clipboard b"52" => { @@ -852,9 +850,9 @@ impl<'a, H, W> vte::Perform for Performer<'a, H, W> self.handler.set_clipboard(utf8_string); } } - } + }, } - } + }, // Reset color index b"104" => { @@ -873,7 +871,7 @@ impl<'a, H, W> vte::Perform for Performer<'a, H, W> None => unhandled(params), } } - } + }, // Reset foreground color b"110" => self.handler.reset_color(NamedColor::Foreground as usize), @@ -889,35 +887,27 @@ impl<'a, H, W> vte::Perform for Performer<'a, H, W> } #[inline] - fn csi_dispatch( - &mut self, - args: &[i64], - intermediates: &[u8], - _ignore: bool, - action: char - ) { + fn csi_dispatch(&mut self, args: &[i64], intermediates: &[u8], _ignore: bool, action: char) { let private = intermediates.get(0).map(|b| *b == b'?').unwrap_or(false); let handler = &mut self.handler; let writer = &mut self.writer; macro_rules! unhandled { () => {{ - debug!("[Unhandled CSI] action={:?}, args={:?}, intermediates={:?}", - action, args, intermediates); + debug!( + "[Unhandled CSI] action={:?}, args={:?}, intermediates={:?}", + action, args, intermediates + ); return; - }} + }}; } macro_rules! arg_or_default { (idx: $idx:expr, default: $default:expr) => { - args.get($idx).and_then(|v| { - if *v == 0 { - None - } else { - Some(*v) - } - }).unwrap_or($default) - } + args.get($idx) + .and_then(|v| if *v == 0 { None } else { Some(*v) }) + .unwrap_or($default) + }; } match action { @@ -930,8 +920,7 @@ impl<'a, H, W> vte::Perform for Performer<'a, H, W> for _ in 0..arg_or_default!(idx: 0, default: 1) { handler.input(c); } - } - else { + } else { debug!("tried to repeat with no preceding char"); } }, @@ -1012,7 +1001,8 @@ impl<'a, H, W> vte::Perform for Performer<'a, H, W> return; } loop { - if i >= args.len() { // C-for condition + if i >= args.len() { + // C-for condition break; } @@ -1061,7 +1051,7 @@ impl<'a, H, W> vte::Perform for Performer<'a, H, W> 45 => Attr::Background(Color::Named(NamedColor::Magenta)), 46 => Attr::Background(Color::Named(NamedColor::Cyan)), 47 => Attr::Background(Color::Named(NamedColor::White)), - 48 => { + 48 => { let mut start = 0; if let Some(color) = parse_color(&args[i..], &mut start) { i += start; @@ -1094,7 +1084,7 @@ impl<'a, H, W> vte::Perform for Performer<'a, H, W> i += 1; // C-for expr } - } + }, 'n' => handler.device_status(writer, arg_or_default!(idx: 0, default: 0) as usize), 'r' => { if private { @@ -1119,29 +1109,25 @@ impl<'a, H, W> vte::Perform for Performer<'a, H, W> 1 | 2 => Some(CursorStyle::Block), 3 | 4 => Some(CursorStyle::Underline), 5 | 6 => Some(CursorStyle::Beam), - _ => unhandled!() + _ => unhandled!(), }; handler.set_cursor_style(style); - } + }, _ => unhandled!(), } } #[inline] - fn esc_dispatch( - &mut self, - params: &[i64], - intermediates: &[u8], - _ignore: bool, - byte: u8 - ) { + fn esc_dispatch(&mut self, params: &[i64], intermediates: &[u8], _ignore: bool, byte: u8) { macro_rules! unhandled { () => {{ - debug!("[unhandled] esc_dispatch params={:?}, ints={:?}, byte={:?} ({:02x})", - params, intermediates, byte as char, byte); + debug!( + "[unhandled] esc_dispatch params={:?}, ints={:?}, byte={:?} ({:02x})", + params, intermediates, byte as char, byte + ); return; - }} + }}; } macro_rules! configure_charset { @@ -1154,7 +1140,7 @@ impl<'a, H, W> vte::Perform for Performer<'a, H, W> _ => unhandled!(), }; self.handler.configure_charset(index, $charset) - }} + }}; } match byte { @@ -1163,7 +1149,7 @@ impl<'a, H, W> vte::Perform for Performer<'a, H, W> b'E' => { self.handler.linefeed(); self.handler.carriage_return(); - } + }, b'H' => self.handler.set_horizontal_tabstop(), b'M' => self.handler.reverse_index(), b'Z' => self.handler.identify_terminal(self.writer), @@ -1176,7 +1162,7 @@ impl<'a, H, W> vte::Perform for Performer<'a, H, W> } else { self.handler.restore_cursor_position(); } - } + }, b'=' => self.handler.set_keypad_application_mode(), b'>' => self.handler.unset_keypad_application_mode(), b'\\' => (), // String terminator, do nothing (parser handles as string terminator) @@ -1185,14 +1171,13 @@ impl<'a, H, W> vte::Perform for Performer<'a, H, W> } } - /// Parse a color specifier from list of attributes fn parse_color(attrs: &[i64], i: &mut usize) -> Option { if attrs.len() < 2 { return None; } - match attrs[*i+1] { + match attrs[*i + 1] { 2 => { // RGB color spec if attrs.len() < 5 { @@ -1200,9 +1185,9 @@ fn parse_color(attrs: &[i64], i: &mut usize) -> Option { return None; } - let r = attrs[*i+2]; - let g = attrs[*i+3]; - let b = attrs[*i+4]; + let r = attrs[*i + 2]; + let g = attrs[*i + 3]; + let b = attrs[*i + 4]; *i += 4; @@ -1212,11 +1197,7 @@ fn parse_color(attrs: &[i64], i: &mut usize) -> Option { return None; } - Some(Color::Spec(Rgb { - r: r as u8, - g: g as u8, - b: b as u8 - })) + Some(Color::Spec(Rgb { r: r as u8, g: g as u8, b: b as u8 })) }, 5 => { if attrs.len() < 3 { @@ -1226,20 +1207,18 @@ fn parse_color(attrs: &[i64], i: &mut usize) -> Option { *i += 2; let idx = attrs[*i]; match idx { - 0 ..= 255 => { - Some(Color::Indexed(idx as u8)) - }, + 0..=255 => Some(Color::Indexed(idx as u8)), _ => { debug!("Invalid color index: {}", idx); None - } + }, } } }, _ => { - debug!("Unexpected color attr: {}", attrs[*i+1]); + debug!("Unexpected color attr: {}", attrs[*i + 1]); None - } + }, } } @@ -1314,7 +1293,6 @@ pub mod C0 { pub const DEL: u8 = 0x7f; } - /// C1 set of 8-bit control characters (from ANSI X3.64-1979) /// /// 0x80 (@), 0x81 (A), 0x82 (B), 0x83 (C) are reserved @@ -1393,10 +1371,13 @@ pub mod C1 { // Byte sequences used in these tests are recording of pty stdout. #[cfg(test)] mod tests { - use std::io; - use crate::index::{Line, Column}; - use super::{Processor, Handler, Attr, TermInfo, Color, StandardCharset, CharsetIndex, parse_rgb_color, parse_number}; + use super::{ + parse_number, parse_rgb_color, Attr, CharsetIndex, Color, Handler, Processor, + StandardCharset, TermInfo, + }; + use crate::index::{Column, Line}; use crate::term::color::Rgb; + use std::io; /// The /dev/null of `io::Write` struct Void; @@ -1434,9 +1415,7 @@ mod tests { #[test] fn parse_control_attribute() { - static BYTES: &'static [u8] = &[ - 0x1b, 0x5b, 0x31, 0x6d - ]; + static BYTES: &'static [u8] = &[0x1b, 0x5b, 0x31, 0x6d]; let mut parser = Processor::new(); let mut handler = AttrHandler::default(); @@ -1451,8 +1430,8 @@ mod tests { #[test] fn parse_truecolor_attr() { static BYTES: &'static [u8] = &[ - 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x32, 0x3b, 0x31, 0x32, - 0x38, 0x3b, 0x36, 0x36, 0x3b, 0x32, 0x35, 0x35, 0x6d + 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x32, 0x3b, 0x31, 0x32, 0x38, 0x3b, 0x36, 0x36, 0x3b, + 0x32, 0x35, 0x35, 0x6d, ]; let mut parser = Processor::new(); @@ -1462,11 +1441,7 @@ mod tests { parser.advance(&mut handler, *byte, &mut Void); } - let spec = Rgb { - r: 128, - g: 66, - b: 255 - }; + let spec = Rgb { r: 128, g: 66, b: 255 }; assert_eq!(handler.attr, Some(Attr::Foreground(Color::Spec(spec)))); } @@ -1475,22 +1450,19 @@ mod tests { #[test] fn parse_zsh_startup() { static BYTES: &'static [u8] = &[ - 0x1b, 0x5b, 0x31, 0x6d, 0x1b, 0x5b, 0x37, 0x6d, 0x25, 0x1b, 0x5b, - 0x32, 0x37, 0x6d, 0x1b, 0x5b, 0x31, 0x6d, 0x1b, 0x5b, 0x30, 0x6d, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x0d, 0x20, 0x0d, 0x0d, 0x1b, 0x5b, 0x30, 0x6d, 0x1b, - 0x5b, 0x32, 0x37, 0x6d, 0x1b, 0x5b, 0x32, 0x34, 0x6d, 0x1b, 0x5b, - 0x4a, 0x6a, 0x77, 0x69, 0x6c, 0x6d, 0x40, 0x6a, 0x77, 0x69, 0x6c, - 0x6d, 0x2d, 0x64, 0x65, 0x73, 0x6b, 0x20, 0x1b, 0x5b, 0x30, 0x31, - 0x3b, 0x33, 0x32, 0x6d, 0xe2, 0x9e, 0x9c, 0x20, 0x1b, 0x5b, 0x30, - 0x31, 0x3b, 0x33, 0x32, 0x6d, 0x20, 0x1b, 0x5b, 0x33, 0x36, 0x6d, - 0x7e, 0x2f, 0x63, 0x6f, 0x64, 0x65 + 0x1b, 0x5b, 0x31, 0x6d, 0x1b, 0x5b, 0x37, 0x6d, 0x25, 0x1b, 0x5b, 0x32, 0x37, 0x6d, + 0x1b, 0x5b, 0x31, 0x6d, 0x1b, 0x5b, 0x30, 0x6d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x0d, 0x20, 0x0d, 0x0d, 0x1b, 0x5b, 0x30, 0x6d, 0x1b, 0x5b, 0x32, + 0x37, 0x6d, 0x1b, 0x5b, 0x32, 0x34, 0x6d, 0x1b, 0x5b, 0x4a, 0x6a, 0x77, 0x69, 0x6c, + 0x6d, 0x40, 0x6a, 0x77, 0x69, 0x6c, 0x6d, 0x2d, 0x64, 0x65, 0x73, 0x6b, 0x20, 0x1b, + 0x5b, 0x30, 0x31, 0x3b, 0x33, 0x32, 0x6d, 0xe2, 0x9e, 0x9c, 0x20, 0x1b, 0x5b, 0x30, + 0x31, 0x3b, 0x33, 0x32, 0x6d, 0x20, 0x1b, 0x5b, 0x33, 0x36, 0x6d, 0x7e, 0x2f, 0x63, + 0x6f, 0x64, 0x65, ]; let mut handler = AttrHandler::default(); @@ -1508,10 +1480,7 @@ mod tests { impl Default for CharsetHandler { fn default() -> CharsetHandler { - CharsetHandler { - index: CharsetIndex::G0, - charset: StandardCharset::Ascii, - } + CharsetHandler { index: CharsetIndex::G0, charset: StandardCharset::Ascii } } } @@ -1527,8 +1496,13 @@ mod tests { } impl TermInfo for CharsetHandler { - fn lines(&self) -> Line { Line(200) } - fn cols(&self) -> Column { Column(90) } + fn lines(&self) -> Line { + Line(200) + } + + fn cols(&self) -> Column { + Column(90) + } } #[test] diff --git a/src/cli.rs b/src/cli.rs index f134f35..6089ac2 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -11,14 +11,14 @@ // 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 ::log; -use clap::{Arg, App, crate_name, crate_version, crate_authors, crate_description}; +use clap::{crate_authors, crate_description, crate_name, crate_version, App, Arg}; +use log; -use crate::index::{Line, Column}; -use crate::config::{Dimensions, Delta, Shell}; -use crate::window::{DEFAULT_NAME}; -use std::path::{Path, PathBuf}; +use crate::config::{Delta, Dimensions, Shell}; +use crate::index::{Column, Line}; +use crate::window::DEFAULT_NAME; use std::borrow::Cow; +use std::path::{Path, PathBuf}; /// Options specified on the command line pub struct Options { @@ -64,70 +64,95 @@ impl Options { .version(crate_version!()) .author(crate_authors!("\n")) .about(crate_description!()) - .arg(Arg::with_name("ref-test") - .long("ref-test") - .help("Generates ref test")) - .arg(Arg::with_name("live-config-reload") - .long("live-config-reload") - .help("Enable automatic config reloading")) - .arg(Arg::with_name("no-live-config-reload") - .long("no-live-config-reload") - .help("Disable automatic config reloading") - .conflicts_with("live-config-reload")) - .arg(Arg::with_name("print-events") - .long("print-events") - .help("Print all events to stdout")) - .arg(Arg::with_name("persistent-logging") - .long("persistent-logging") - .help("Keep the log file after quitting Alacritty")) - .arg(Arg::with_name("dimensions") - .long("dimensions") - .short("d") - .value_names(&["columns", "lines"]) - .help("Defines the window dimensions. Falls back to size specified by \ - window manager if set to 0x0 [default: 0x0]")) - .arg(Arg::with_name("position") - .long("position") - .allow_hyphen_values(true) - .value_names(&["x-pos", "y-pos"]) - .help("Defines the window position. Falls back to position specified by \ - window manager if unset [default: unset]")) - .arg(Arg::with_name("title") - .long("title") - .short("t") - .takes_value(true) - .help(&format!("Defines the window title [default: {}]", DEFAULT_NAME))) - .arg(Arg::with_name("class") - .long("class") - .takes_value(true) - .help(&format!("Defines window class on Linux [default: {}]", DEFAULT_NAME))) - .arg(Arg::with_name("q") - .short("q") - .multiple(true) - .conflicts_with("v") - .help("Reduces the level of verbosity (the min level is -qq)")) - .arg(Arg::with_name("v") - .short("v") - .multiple(true) - .conflicts_with("q") - .help("Increases the level of verbosity (the max level is -vvv)")) - .arg(Arg::with_name("working-directory") - .long("working-directory") - .takes_value(true) - .help("Start the shell in the specified working directory")) - .arg(Arg::with_name("config-file") - .long("config-file") - .takes_value(true) - .help("Specify alternative configuration file \ - [default: $XDG_CONFIG_HOME/alacritty/alacritty.yml]")) - .arg(Arg::with_name("command") - .long("command") - .short("e") - .multiple(true) - .takes_value(true) - .min_values(1) - .allow_hyphen_values(true) - .help("Command and args to execute (must be last argument)")) + .arg(Arg::with_name("ref-test").long("ref-test").help("Generates ref test")) + .arg( + Arg::with_name("live-config-reload") + .long("live-config-reload") + .help("Enable automatic config reloading"), + ) + .arg( + Arg::with_name("no-live-config-reload") + .long("no-live-config-reload") + .help("Disable automatic config reloading") + .conflicts_with("live-config-reload"), + ) + .arg( + Arg::with_name("print-events") + .long("print-events") + .help("Print all events to stdout"), + ) + .arg( + Arg::with_name("persistent-logging") + .long("persistent-logging") + .help("Keep the log file after quitting Alacritty"), + ) + .arg( + Arg::with_name("dimensions") + .long("dimensions") + .short("d") + .value_names(&["columns", "lines"]) + .help( + "Defines the window dimensions. Falls back to size specified by window \ + manager if set to 0x0 [default: 0x0]", + ), + ) + .arg( + Arg::with_name("position") + .long("position") + .allow_hyphen_values(true) + .value_names(&["x-pos", "y-pos"]) + .help( + "Defines the window position. Falls back to position specified by window \ + manager if unset [default: unset]", + ), + ) + .arg( + Arg::with_name("title") + .long("title") + .short("t") + .takes_value(true) + .help(&format!("Defines the window title [default: {}]", DEFAULT_NAME)), + ) + .arg( + Arg::with_name("class") + .long("class") + .takes_value(true) + .help(&format!("Defines window class on Linux [default: {}]", DEFAULT_NAME)), + ) + .arg( + Arg::with_name("q") + .short("q") + .multiple(true) + .conflicts_with("v") + .help("Reduces the level of verbosity (the min level is -qq)"), + ) + .arg( + Arg::with_name("v") + .short("v") + .multiple(true) + .conflicts_with("q") + .help("Increases the level of verbosity (the max level is -vvv)"), + ) + .arg( + Arg::with_name("working-directory") + .long("working-directory") + .takes_value(true) + .help("Start the shell in the specified working directory"), + ) + .arg(Arg::with_name("config-file").long("config-file").takes_value(true).help( + "Specify alternative configuration file [default: \ + $XDG_CONFIG_HOME/alacritty/alacritty.yml]", + )) + .arg( + Arg::with_name("command") + .long("command") + .short("e") + .multiple(true) + .takes_value(true) + .min_values(1) + .allow_hyphen_values(true) + .help("Command and args to execute (must be last argument)"), + ) .get_matches(); if matches.is_present("ref-test") { @@ -170,14 +195,14 @@ impl Options { match matches.occurrences_of("q") { 0 => {}, 1 => options.log_level = log::LevelFilter::Error, - 2 | _ => options.log_level = log::LevelFilter::Off + 2 | _ => options.log_level = log::LevelFilter::Off, } match matches.occurrences_of("v") { 0 if !options.print_events => {}, 0 | 1 => options.log_level = log::LevelFilter::Info, 2 => options.log_level = log::LevelFilter::Debug, - 3 | _ => options.log_level = log::LevelFilter::Trace + 3 | _ => options.log_level = log::LevelFilter::Trace, } if let Some(dir) = matches.value_of("working-directory") { diff --git a/src/config/bindings.rs b/src/config/bindings.rs index 3e76acc..0e00f6f 100644 --- a/src/config/bindings.rs +++ b/src/config/bindings.rs @@ -11,11 +11,11 @@ // 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 glutin::{MouseButton, ModifiersState}; +use glutin::{ModifiersState, MouseButton}; -use crate::input::{MouseBinding, KeyBinding, Action}; -use crate::term::TermMode; use super::Key; +use crate::input::{Action, KeyBinding, MouseBinding}; +use crate::term::TermMode; macro_rules! bindings { ( diff --git a/src/config/mod.rs b/src/config/mod.rs index 2fa60da..94e74e4 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -4,27 +4,27 @@ //! parameters including font family and style, font size, etc. In the future, //! the config file will also hold user and platform specific keybindings. use std::borrow::Cow; -use std::{env, fmt}; +use std::collections::HashMap; use std::fs::File; use std::io::{self, Read, Write}; use std::path::{Path, PathBuf}; use std::str::FromStr; use std::sync::mpsc; use std::time::Duration; -use std::collections::HashMap; +use std::{env, fmt}; use font::Size; -use serde_yaml; -use serde::{self, de, Deserialize}; -use serde::de::Error as SerdeError; -use serde::de::{Visitor, MapAccess, Unexpected}; -use notify::{Watcher, watcher, DebouncedEvent, RecursiveMode}; use glutin::ModifiersState; +use notify::{watcher, DebouncedEvent, RecursiveMode, Watcher}; +use serde::de::Error as SerdeError; +use serde::de::{MapAccess, Unexpected, Visitor}; +use serde::{self, de, Deserialize}; +use serde_yaml; +use crate::ansi::{Color, CursorStyle, NamedColor}; use crate::cli::Options; -use crate::input::{Action, Binding, MouseBinding, KeyBinding}; -use crate::index::{Line, Column}; -use crate::ansi::{CursorStyle, NamedColor, Color}; +use crate::index::{Column, Line}; +use crate::input::{Action, Binding, KeyBinding, MouseBinding}; use crate::term::color::Rgb; mod bindings; @@ -53,7 +53,8 @@ impl Default for Selection { } fn deserialize_escape_chars<'a, D>(deserializer: D) -> ::std::result::Result - where D: de::Deserializer<'a> +where + D: de::Deserializer<'a>, { match String::deserialize(deserializer) { Ok(escape_chars) => Ok(escape_chars), @@ -86,7 +87,8 @@ fn default_threshold_ms() -> Duration { } fn deserialize_duration_ms<'a, D>(deserializer: D) -> ::std::result::Result - where D: de::Deserializer<'a> +where + D: de::Deserializer<'a>, { match u64::deserialize(deserializer) { Ok(threshold_ms) => Ok(Duration::from_millis(threshold_ms)), @@ -125,8 +127,11 @@ pub struct Url { pub modifiers: ModifiersState, } -fn deserialize_launcher<'a, D>(deserializer: D) -> ::std::result::Result, D::Error> - where D: de::Deserializer<'a> +fn deserialize_launcher<'a, D>( + deserializer: D, +) -> ::std::result::Result, D::Error> +where + D: de::Deserializer<'a>, { let default = Url::default().launcher; @@ -168,7 +173,8 @@ impl Default for Url { } fn deserialize_modifiers<'a, D>(deserializer: D) -> ::std::result::Result - where D: de::Deserializer<'a> +where + D: de::Deserializer<'a>, { ModsWrapper::deserialize(deserializer).map(ModsWrapper::into_inner) } @@ -177,15 +183,15 @@ fn deserialize_modifiers<'a, D>(deserializer: D) -> ::std::result::Result { impl<'a> Shell<'a> { pub fn new(program: S) -> Shell<'a> - where S: Into> + where + S: Into>, { - Shell { - program: program.into(), - args: Vec::new(), - } + Shell { program: program.into(), args: Vec::new() } } pub fn new_with_args(program: S, args: Vec) -> Shell<'a> - where S: Into> + where + S: Into>, { - Shell { - program: program.into(), - args, - } + Shell { program: program.into(), args } } pub fn program(&self) -> &str { @@ -332,9 +334,9 @@ impl Default for Decorations { impl<'de> Deserialize<'de> for Decorations { fn deserialize(deserializer: D) -> ::std::result::Result - where D: de::Deserializer<'de> + where + D: de::Deserializer<'de>, { - struct DecorationsVisitor; impl<'de> Visitor<'de> for DecorationsVisitor { @@ -346,7 +348,8 @@ impl<'de> Deserialize<'de> for Decorations { #[cfg(target_os = "macos")] fn visit_str(self, value: &str) -> ::std::result::Result - where E: de::Error + where + E: de::Error, { match value.to_lowercase().as_str() { "transparent" => Ok(Decorations::Transparent), @@ -354,41 +357,46 @@ impl<'de> Deserialize<'de> for Decorations { "none" => Ok(Decorations::None), "full" => Ok(Decorations::Full), "true" => { - error!("Deprecated decorations boolean value, \ - use one of transparent|buttonless|none|full instead; \ - falling back to \"full\""); + error!( + "Deprecated decorations boolean value, use one of \ + transparent|buttonless|none|full instead; falling back to \"full\"" + ); Ok(Decorations::Full) }, "false" => { - error!("Deprecated decorations boolean value, \ - use one of transparent|buttonless|none|full instead; \ - falling back to \"none\""); + error!( + "Deprecated decorations boolean value, use one of \ + transparent|buttonless|none|full instead; falling back to \"none\"" + ); Ok(Decorations::None) }, _ => { error!("Invalid decorations value: {}; using default value", value); Ok(Decorations::Full) - } + }, } } #[cfg(not(target_os = "macos"))] fn visit_str(self, value: &str) -> ::std::result::Result - where E: de::Error + where + E: de::Error, { match value.to_lowercase().as_str() { "none" => Ok(Decorations::None), "full" => Ok(Decorations::Full), "true" => { - error!("Deprecated decorations boolean value, \ - use one of none|full instead; \ - falling back to \"full\""); + error!( + "Deprecated decorations boolean value, use one of none|full instead; \ + falling back to \"full\"" + ); Ok(Decorations::Full) }, "false" => { - error!("Deprecated decorations boolean value, \ - use one of none|full instead; \ - falling back to \"none\""); + error!( + "Deprecated decorations boolean value, use one of none|full instead; \ + falling back to \"none\"" + ); Ok(Decorations::None) }, "transparent" | "buttonless" => { @@ -398,7 +406,7 @@ impl<'de> Deserialize<'de> for Decorations { _ => { error!("Invalid decorations value: {}; using default value", value); Ok(Decorations::Full) - } + }, } } } @@ -437,7 +445,7 @@ pub struct WindowConfig { impl Default for WindowConfig { fn default() -> Self { - WindowConfig{ + WindowConfig { dimensions: Default::default(), position: Default::default(), padding: default_padding(), @@ -453,7 +461,8 @@ fn default_padding() -> Delta { } fn deserialize_padding<'a, D>(deserializer: D) -> ::std::result::Result, D::Error> - where D: de::Deserializer<'a> +where + D: de::Deserializer<'a>, { match Delta::deserialize(deserializer) { Ok(delta) => Ok(delta), @@ -513,11 +522,11 @@ pub struct Config { window: WindowConfig, /// Keybindings - #[serde(default="default_key_bindings", deserialize_with = "deserialize_key_bindings")] + #[serde(default = "default_key_bindings", deserialize_with = "deserialize_key_bindings")] key_bindings: Vec, /// Bindings for the mouse - #[serde(default="default_mouse_bindings", deserialize_with = "deserialize_mouse_bindings")] + #[serde(default = "default_mouse_bindings", deserialize_with = "deserialize_mouse_bindings")] mouse_bindings: Vec, #[serde(default, deserialize_with = "failure_default")] @@ -590,8 +599,7 @@ pub struct Config { impl Default for Config { fn default() -> Self { - serde_yaml::from_str(DEFAULT_ALACRITTY_CONFIG) - .expect("default config is invalid") + serde_yaml::from_str(DEFAULT_ALACRITTY_CONFIG).expect("default config is invalid") } } @@ -603,24 +611,28 @@ fn default_mouse_bindings() -> Vec { bindings::default_mouse_bindings() } -fn deserialize_key_bindings<'a, D>(deserializer: D) - -> ::std::result::Result, D::Error> +fn deserialize_key_bindings<'a, D>( + deserializer: D, +) -> ::std::result::Result, D::Error> where D: de::Deserializer<'a>, { deserialize_bindings(deserializer, bindings::default_key_bindings()) } -fn deserialize_mouse_bindings<'a, D>(deserializer: D) - -> ::std::result::Result, D::Error> +fn deserialize_mouse_bindings<'a, D>( + deserializer: D, +) -> ::std::result::Result, D::Error> where D: de::Deserializer<'a>, { deserialize_bindings(deserializer, bindings::default_mouse_bindings()) } -fn deserialize_bindings<'a, D, T>(deserializer: D, mut default: Vec>) - -> ::std::result::Result>, D::Error> +fn deserialize_bindings<'a, D, T>( + deserializer: D, + mut default: Vec>, +) -> ::std::result::Result>, D::Error> where D: de::Deserializer<'a>, T: Copy + Eq + std::hash::Hash + std::fmt::Debug, @@ -638,8 +650,9 @@ where } fn failure_default_vec<'a, D, T>(deserializer: D) -> ::std::result::Result, D::Error> - where D: de::Deserializer<'a>, - T: Deserialize<'a> +where + D: de::Deserializer<'a>, + T: Deserialize<'a>, { // Deserialize as generic vector let vec = match Vec::::deserialize(deserializer) { @@ -669,7 +682,8 @@ fn default_tabspaces() -> usize { } fn deserialize_tabspaces<'a, D>(deserializer: D) -> ::std::result::Result - where D: de::Deserializer<'a> +where + D: de::Deserializer<'a>, { match usize::deserialize(deserializer) { Ok(value) => Ok(value), @@ -681,7 +695,8 @@ fn deserialize_tabspaces<'a, D>(deserializer: D) -> ::std::result::Result(deserializer: D) -> ::std::result::Result - where D: de::Deserializer<'a> +where + D: de::Deserializer<'a>, { match bool::deserialize(deserializer) { Ok(value) => Ok(value), @@ -696,10 +711,10 @@ fn default_true_bool() -> bool { true } -fn failure_default<'a, D, T>(deserializer: D) - -> ::std::result::Result - where D: de::Deserializer<'a>, - T: Deserialize<'a> + Default +fn failure_default<'a, D, T>(deserializer: D) -> ::std::result::Result +where + D: de::Deserializer<'a>, + T: Deserialize<'a> + Default, { match T::deserialize(deserializer) { Ok(value) => Ok(value), @@ -745,7 +760,8 @@ fn default_scrolling_multiplier() -> u8 { } fn deserialize_scrolling_history<'a, D>(deserializer: D) -> ::std::result::Result - where D: de::Deserializer<'a> +where + D: de::Deserializer<'a>, { match u32::deserialize(deserializer) { Ok(lines) => { @@ -768,7 +784,8 @@ fn deserialize_scrolling_history<'a, D>(deserializer: D) -> ::std::result::Resul } fn deserialize_scrolling_multiplier<'a, D>(deserializer: D) -> ::std::result::Result - where D: de::Deserializer<'a> +where + D: de::Deserializer<'a>, { match u8::deserialize(deserializer) { Ok(lines) => Ok(lines), @@ -794,7 +811,8 @@ impl ModsWrapper { impl<'a> de::Deserialize<'a> for ModsWrapper { fn deserialize(deserializer: D) -> ::std::result::Result - where D: de::Deserializer<'a> + where + D: de::Deserializer<'a>, { struct ModsVisitor; @@ -806,7 +824,8 @@ impl<'a> de::Deserialize<'a> for ModsWrapper { } fn visit_str(self, value: &str) -> ::std::result::Result - where E: de::Error, + where + E: de::Error, { let mut res = ModifiersState::default(); for modifier in value.split('|') { @@ -838,7 +857,8 @@ impl ActionWrapper { impl<'a> de::Deserialize<'a> for ActionWrapper { fn deserialize(deserializer: D) -> ::std::result::Result - where D: de::Deserializer<'a> + where + D: de::Deserializer<'a>, { struct ActionVisitor; @@ -846,14 +866,16 @@ impl<'a> de::Deserialize<'a> for ActionWrapper { type Value = ActionWrapper; fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("Paste, Copy, PasteSelection, IncreaseFontSize, DecreaseFontSize, \ - ResetFontSize, ScrollPageUp, ScrollPageDown, ScrollToTop, \ - ScrollToBottom, ClearHistory, Hide, ClearLogNotice, SpawnNewInstance, \ - None or Quit") + f.write_str( + "Paste, Copy, PasteSelection, IncreaseFontSize, DecreaseFontSize, \ + ResetFontSize, ScrollPageUp, ScrollPageDown, ScrollToTop, ScrollToBottom, \ + ClearHistory, Hide, ClearLogNotice, SpawnNewInstance, None or Quit", + ) } fn visit_str(self, value: &str) -> ::std::result::Result - where E: de::Error, + where + E: de::Error, { Ok(ActionWrapper(match value { "Paste" => Action::Paste, @@ -915,8 +937,9 @@ struct ModeWrapper { } impl<'a> de::Deserialize<'a> for ModeWrapper { - fn deserialize(deserializer: D) -> ::std::result::Result - where D: de::Deserializer<'a> + fn deserialize(deserializer: D) -> ::std::result::Result + where + D: de::Deserializer<'a>, { struct ModeVisitor; @@ -928,12 +951,10 @@ impl<'a> de::Deserialize<'a> for ModeWrapper { } fn visit_str(self, value: &str) -> ::std::result::Result - where E: de::Error, + where + E: de::Error, { - let mut res = ModeWrapper { - mode: TermMode::empty(), - not_mode: TermMode::empty() - }; + let mut res = ModeWrapper { mode: TermMode::empty(), not_mode: TermMode::empty() }; for modifier in value.split('|') { match modifier.trim() { @@ -964,7 +985,8 @@ impl MouseButton { impl<'a> de::Deserialize<'a> for MouseButton { fn deserialize(deserializer: D) -> ::std::result::Result - where D: de::Deserializer<'a> + where + D: de::Deserializer<'a>, { struct MouseButtonVisitor; @@ -976,7 +998,8 @@ impl<'a> de::Deserialize<'a> for MouseButton { } fn visit_str(self, value: &str) -> ::std::result::Result - where E: de::Error, + where + E: de::Error, { match value { "Left" => Ok(MouseButton(::glutin::MouseButton::Left)), @@ -988,7 +1011,7 @@ impl<'a> de::Deserialize<'a> for MouseButton { } else { Err(E::invalid_value(Unexpected::Str(value), &self)) } - } + }, } } } @@ -1041,7 +1064,8 @@ impl RawBinding { impl<'a> de::Deserialize<'a> for RawBinding { fn deserialize(deserializer: D) -> ::std::result::Result - where D: de::Deserializer<'a> + where + D: de::Deserializer<'a>, { enum Field { Key, @@ -1055,13 +1079,13 @@ impl<'a> de::Deserialize<'a> for RawBinding { impl<'a> de::Deserialize<'a> for Field { fn deserialize(deserializer: D) -> ::std::result::Result - where D: de::Deserializer<'a> + where + D: de::Deserializer<'a>, { struct FieldVisitor; - static FIELDS: &'static [&'static str] = &[ - "key", "mods", "mode", "action", "chars", "mouse", "command", - ]; + static FIELDS: &'static [&'static str] = + &["key", "mods", "mode", "action", "chars", "mouse", "command"]; impl<'a> Visitor<'a> for FieldVisitor { type Value = Field; @@ -1071,7 +1095,8 @@ impl<'a> de::Deserialize<'a> for RawBinding { } fn visit_str(self, value: &str) -> ::std::result::Result - where E: de::Error, + where + E: de::Error, { match value { "key" => Ok(Field::Key), @@ -1098,11 +1123,9 @@ impl<'a> de::Deserialize<'a> for RawBinding { f.write_str("binding specification") } - fn visit_map( - self, - mut map: V - ) -> ::std::result::Result - where V: MapAccess<'a>, + fn visit_map(self, mut map: V) -> ::std::result::Result + where + V: MapAccess<'a>, { let mut mods: Option = None; let mut key: Option = None; @@ -1133,8 +1156,7 @@ impl<'a> de::Deserialize<'a> for RawBinding { } key = Some(Key::Scancode(scancode as u32)); } else { - let k = Key::deserialize(val) - .map_err(V::Error::custom)?; + let k = Key::deserialize(val).map_err(V::Error::custom)?; key = Some(k); } }, @@ -1188,18 +1210,18 @@ impl<'a> de::Deserialize<'a> for RawBinding { 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, 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")) }, - (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); @@ -1210,29 +1232,20 @@ impl<'a> de::Deserialize<'a> for RawBinding { return Err(V::Error::custom("bindings require mouse button or key")); } - Ok(RawBinding { - mode, - notmode: not_mode, - action, - key, - mouse, - mods, - }) + Ok(RawBinding { mode, notmode: not_mode, action, key, mouse, mods }) } } - const FIELDS: &[&str] = &[ - "key", "mods", "mode", "action", "chars", "mouse", "command", - ]; + const FIELDS: &[&str] = &["key", "mods", "mode", "action", "chars", "mouse", "command"]; deserializer.deserialize_struct("RawBinding", FIELDS, RawBindingVisitor) } } - impl<'a> de::Deserialize<'a> for Alpha { fn deserialize(deserializer: D) -> ::std::result::Result - where D: de::Deserializer<'a> + where + D: de::Deserializer<'a>, { let value = f32::deserialize(deserializer)?; Ok(Alpha::new(value)) @@ -1241,21 +1254,21 @@ impl<'a> de::Deserialize<'a> for Alpha { impl<'a> de::Deserialize<'a> for MouseBinding { fn deserialize(deserializer: D) -> ::std::result::Result - where D: de::Deserializer<'a> + where + D: de::Deserializer<'a>, { let raw = RawBinding::deserialize(deserializer)?; - raw.into_mouse_binding() - .map_err(|_| D::Error::custom("expected mouse binding")) + raw.into_mouse_binding().map_err(|_| D::Error::custom("expected mouse binding")) } } impl<'a> de::Deserialize<'a> for KeyBinding { fn deserialize(deserializer: D) -> ::std::result::Result - where D: de::Deserializer<'a> + where + D: de::Deserializer<'a>, { let raw = RawBinding::deserialize(deserializer)?; - raw.into_key_binding() - .map_err(|_| D::Error::custom("expected key binding")) + raw.into_key_binding().map_err(|_| D::Error::custom("expected key binding")) } } @@ -1313,32 +1326,33 @@ impl Default for Colors { fn default_normal_colors() -> AnsiColors { AnsiColors { - black: Rgb {r: 0x00, g: 0x00, b: 0x00}, - red: Rgb {r: 0xd5, g: 0x4e, b: 0x53}, - green: Rgb {r: 0xb9, g: 0xca, b: 0x4a}, - yellow: Rgb {r: 0xe6, g: 0xc5, b: 0x47}, - blue: Rgb {r: 0x7a, g: 0xa6, b: 0xda}, - magenta: Rgb {r: 0xc3, g: 0x97, b: 0xd8}, - cyan: Rgb {r: 0x70, g: 0xc0, b: 0xba}, - white: Rgb {r: 0xea, g: 0xea, b: 0xea}, + black: Rgb { r: 0x00, g: 0x00, b: 0x00 }, + red: Rgb { r: 0xd5, g: 0x4e, b: 0x53 }, + green: Rgb { r: 0xb9, g: 0xca, b: 0x4a }, + yellow: Rgb { r: 0xe6, g: 0xc5, b: 0x47 }, + blue: Rgb { r: 0x7a, g: 0xa6, b: 0xda }, + magenta: Rgb { r: 0xc3, g: 0x97, b: 0xd8 }, + cyan: Rgb { r: 0x70, g: 0xc0, b: 0xba }, + white: Rgb { r: 0xea, g: 0xea, b: 0xea }, } } fn default_bright_colors() -> AnsiColors { AnsiColors { - black: Rgb {r: 0x66, g: 0x66, b: 0x66}, - red: Rgb {r: 0xff, g: 0x33, b: 0x34}, - green: Rgb {r: 0x9e, g: 0xc4, b: 0x00}, - yellow: Rgb {r: 0xe7, g: 0xc5, b: 0x47}, - blue: Rgb {r: 0x7a, g: 0xa6, b: 0xda}, - magenta: Rgb {r: 0xb7, g: 0x7e, b: 0xe0}, - cyan: Rgb {r: 0x54, g: 0xce, b: 0xd6}, - white: Rgb {r: 0xff, g: 0xff, b: 0xff}, + black: Rgb { r: 0x66, g: 0x66, b: 0x66 }, + red: Rgb { r: 0xff, g: 0x33, b: 0x34 }, + green: Rgb { r: 0x9e, g: 0xc4, b: 0x00 }, + yellow: Rgb { r: 0xe7, g: 0xc5, b: 0x47 }, + blue: Rgb { r: 0x7a, g: 0xa6, b: 0xda }, + magenta: Rgb { r: 0xb7, g: 0x7e, b: 0xe0 }, + cyan: Rgb { r: 0x54, g: 0xce, b: 0xd6 }, + white: Rgb { r: 0xff, g: 0xff, b: 0xff }, } } fn deserialize_normal_colors<'a, D>(deserializer: D) -> ::std::result::Result - where D: de::Deserializer<'a> +where + D: de::Deserializer<'a>, { match AnsiColors::deserialize(deserializer) { Ok(escape_chars) => Ok(escape_chars), @@ -1350,7 +1364,8 @@ fn deserialize_normal_colors<'a, D>(deserializer: D) -> ::std::result::Result(deserializer: D) -> ::std::result::Result - where D: de::Deserializer<'a> +where + D: de::Deserializer<'a>, { match AnsiColors::deserialize(deserializer) { Ok(escape_chars) => Ok(escape_chars), @@ -1370,15 +1385,15 @@ pub struct IndexedColor { } fn deserialize_color_index<'a, D>(deserializer: D) -> ::std::result::Result - where D: de::Deserializer<'a> +where + D: de::Deserializer<'a>, { match u8::deserialize(deserializer) { Ok(index) => { if index < 16 { error!( - "Problem with config: indexed_color's index is {}, \ - but a value bigger than 15 was expected; \ - ignoring setting", + "Problem with config: indexed_color's index is {}, but a value bigger than 15 \ + was expected; ignoring setting", index ); @@ -1408,10 +1423,7 @@ pub struct Cursor { impl Default for Cursor { fn default() -> Self { - Self { - style: Default::default(), - unfocused_hollow: true, - } + Self { style: Default::default(), unfocused_hollow: true } } } @@ -1457,8 +1469,11 @@ impl Default for PrimaryColors { } } -fn deserialize_optional_color<'a, D>(deserializer: D) -> ::std::result::Result, D::Error> - where D: de::Deserializer<'a> +fn deserialize_optional_color<'a, D>( + deserializer: D, +) -> ::std::result::Result, D::Error> +where + D: de::Deserializer<'a>, { match Option::deserialize(deserializer) { Ok(Some(color)) => { @@ -1507,7 +1522,8 @@ pub struct AnsiColors { /// This is *not* the deserialize impl for Rgb since we want a symmetric /// serialize/deserialize impl for ref tests. fn rgb_from_hex<'a, D>(deserializer: D) -> ::std::result::Result - where D: de::Deserializer<'a> +where + D: de::Deserializer<'a>, { struct RgbVisitor; @@ -1519,7 +1535,8 @@ fn rgb_from_hex<'a, D>(deserializer: D) -> ::std::result::Result } fn visit_str(self, value: &str) -> ::std::result::Result - where E: ::serde::de::Error + where + E: ::serde::de::Error, { Rgb::from_str(&value[..]) .map_err(|_| E::custom("failed to parse rgb; expected hex color like 0xff00ff")) @@ -1540,6 +1557,7 @@ fn rgb_from_hex<'a, D>(deserializer: D) -> ::std::result::Result impl FromStr for Rgb { type Err = (); + fn from_str(s: &str) -> ::std::result::Result { let mut chars = s.chars(); let mut rgb = Rgb::default(); @@ -1561,7 +1579,11 @@ impl FromStr for Rgb { } match chars.next() { - Some('0') => if chars.next() != Some('x') { return Err(()); }, + Some('0') => { + if chars.next() != Some('x') { + return Err(()); + } + }, Some('#') => (), _ => return Err(()), } @@ -1596,7 +1618,9 @@ impl ::std::error::Error for Error { impl ::std::fmt::Display for Error { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { match *self { - Error::NotFound | Error::Empty => write!(f, "{}", ::std::error::Error::description(self)), + Error::NotFound | Error::Empty => { + write!(f, "{}", ::std::error::Error::description(self)) + }, Error::ReadingEnvHome(ref err) => { write!(f, "Couldn't read $HOME environment variable: {}", err) }, @@ -1646,9 +1670,9 @@ impl Config { .ok() .and_then(|xdg| xdg.find_config_file("alacritty.yml")) .or_else(|| { - ::xdg::BaseDirectories::new().ok().and_then(|fallback| { - fallback.find_config_file("alacritty.yml") - }) + ::xdg::BaseDirectories::new() + .ok() + .and_then(|fallback| fallback.find_config_file("alacritty.yml")) }) .or_else(|| { if let Ok(home) = env::var("HOME") { @@ -1671,10 +1695,8 @@ impl Config { // TODO: Remove old configuration location warning (Deprecated 03/12/2018) #[cfg(windows)] pub fn installed_config<'a>() -> Option> { - let old = dirs::home_dir() - .map(|path| path.join("alacritty.yml")); - let new = dirs::config_dir() - .map(|path| path.join("alacritty\\alacritty.yml")); + let old = dirs::home_dir().map(|path| path.join("alacritty.yml")); + let new = dirs::config_dir().map(|path| path.join("alacritty\\alacritty.yml")); if let Some(old_path) = old.as_ref().filter(|old| old.exists()) { warn!( @@ -1702,11 +1724,9 @@ impl Config { #[cfg(windows)] pub fn write_defaults() -> io::Result> { - let mut path = dirs::config_dir() - .ok_or_else(|| { - io::Error::new(io::ErrorKind::NotFound, "Couldn't find profile directory") - } - )?; + let mut path = dirs::config_dir().ok_or_else(|| { + io::Error::new(io::ErrorKind::NotFound, "Couldn't find profile directory") + })?; path = path.join("alacritty/alacritty.yml"); @@ -1751,8 +1771,7 @@ impl Config { } pub fn padding(&self) -> &Delta { - self.padding.as_ref() - .unwrap_or(&self.window.padding) + self.padding.as_ref().unwrap_or(&self.window.padding) } #[inline] @@ -1808,9 +1827,7 @@ impl Config { } pub fn path(&self) -> Option<&Path> { - self.config_path - .as_ref() - .map(PathBuf::as_path) + self.config_path.as_ref().map(PathBuf::as_path) } pub fn shell(&self) -> Option<&Shell<'_>> { @@ -1912,7 +1929,7 @@ impl Config { Err(err) => { error!("Unable to load config {:?}: {}", path, err); Err(err) - } + }, } } @@ -1933,18 +1950,18 @@ impl Config { fn print_deprecation_warnings(&mut self) { if self.dimensions.is_some() { - warn!("Config dimensions is deprecated; \ - please use window.dimensions instead"); + warn!("Config dimensions is deprecated; please use window.dimensions instead"); } if self.padding.is_some() { - warn!("Config padding is deprecated; \ - please use window.padding instead"); + warn!("Config padding is deprecated; please use window.padding instead"); } if self.mouse.faux_scrollback_lines.is_some() { - warn!("Config mouse.faux_scrollback_lines is deprecated; \ - please use mouse.faux_scrolling_lines instead"); + warn!( + "Config mouse.faux_scrollback_lines is deprecated; please use \ + mouse.faux_scrolling_lines instead" + ); } if let Some(custom_cursor_colors) = self.custom_cursor_colors { @@ -1957,18 +1974,21 @@ impl Config { } if self.cursor_style.is_some() { - warn!("Config cursor_style is deprecated; \ - please use cursor.style instead"); + warn!("Config cursor_style is deprecated; please use cursor.style instead"); } if self.hide_cursor_when_typing.is_some() { - warn!("Config hide_cursor_when_typing is deprecated; \ - please use mouse.hide_when_typing instead"); + warn!( + "Config hide_cursor_when_typing is deprecated; please use mouse.hide_when_typing \ + instead" + ); } if self.unfocused_hollow_cursor.is_some() { - warn!("Config unfocused_hollow_cursor is deprecated; \ - please use cursor.unfocused_hollow instead"); + warn!( + "Config unfocused_hollow_cursor is deprecated; please use cursor.unfocused_hollow \ + instead" + ); } } } @@ -1990,10 +2010,7 @@ pub struct Dimensions { impl Dimensions { pub fn new(columns: Column, lines: Line) -> Self { - Dimensions { - columns, - lines, - } + Dimensions { columns, lines } } /// Get lines @@ -2021,14 +2038,16 @@ pub struct Delta { pub y: T, } -trait DeserializeSize : Sized { +trait DeserializeSize: Sized { fn deserialize<'a, D>(_: D) -> ::std::result::Result - where D: serde::de::Deserializer<'a>; + where + D: serde::de::Deserializer<'a>; } impl DeserializeSize for Size { fn deserialize<'a, D>(deserializer: D) -> ::std::result::Result - where D: serde::de::Deserializer<'a> + where + D: serde::de::Deserializer<'a>, { use std::marker::PhantomData; @@ -2037,7 +2056,8 @@ impl DeserializeSize for Size { } impl<'a, __D> Visitor<'a> for NumVisitor<__D> - where __D: serde::de::Deserializer<'a> + where + __D: serde::de::Deserializer<'a>, { type Value = f64; @@ -2046,20 +2066,22 @@ impl DeserializeSize for Size { } fn visit_f64(self, value: f64) -> ::std::result::Result - where E: ::serde::de::Error + where + E: ::serde::de::Error, { Ok(value) } fn visit_u64(self, value: u64) -> ::std::result::Result - where E: ::serde::de::Error + where + E: ::serde::de::Error, { Ok(value as f64) } } let size = deserializer - .deserialize_any(NumVisitor::{ _marker: PhantomData }) + .deserialize_any(NumVisitor:: { _marker: PhantomData }) .map(|v| Size::new(v as _)); // Use default font size as fallback @@ -2153,10 +2175,7 @@ impl Font { /// Get a font clone with a size modification pub fn with_size(self, size: Size) -> Font { - Font { - size, - .. self - } + Font { size, ..self } } // Get normal font description @@ -2185,8 +2204,10 @@ where { // This is necessary in order to get serde to complete deserialization of the configuration let _ignored = bool::deserialize(deserializer); - error!("The scale_with_dpi setting has been removed, \ - on X11 the WINIT_HIDPI_FACTOR environment variable can be used instead."); + error!( + "The scale_with_dpi setting has been removed, on X11 the WINIT_HIDPI_FACTOR environment \ + variable can be used instead." + ); Ok(None) } @@ -2260,8 +2281,9 @@ impl Monitor { } pub fn new(path: P, mut handler: H) -> Monitor - where H: OnConfigReload + Send + 'static, - P: Into + where + H: OnConfigReload + Send + 'static, + P: Into, { let path = path.into(); @@ -2271,34 +2293,33 @@ impl 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"); + 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) + watcher + .watch(&parent, RecursiveMode::NonRecursive) .expect("watch alacritty.yml dir"); loop { match rx.recv().expect("watcher event") { - DebouncedEvent::Rename(_, _) => continue, + DebouncedEvent::Rename(..) => continue, DebouncedEvent::Write(path) - | DebouncedEvent::Create(path) - | DebouncedEvent::Chmod(path) => - { + | DebouncedEvent::Create(path) + | DebouncedEvent::Chmod(path) => { if path != config_path { continue; } let _ = config_tx.send(path); handler.on_config_reload(); - } - _ => {} + }, + _ => {}, } } }), @@ -2645,13 +2666,13 @@ impl Key { #[cfg(test)] mod tests { - use crate::cli::Options; use super::{Config, DEFAULT_ALACRITTY_CONFIG}; + use crate::cli::Options; #[test] fn parse_config() { - let config: Config = ::serde_yaml::from_str(DEFAULT_ALACRITTY_CONFIG) - .expect("deserialize 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()); @@ -2662,8 +2683,8 @@ mod tests { #[test] fn dynamic_title_ignoring_options_by_default() { - let config: Config = ::serde_yaml::from_str(DEFAULT_ALACRITTY_CONFIG) - .expect("deserialize config"); + let config: Config = + ::serde_yaml::from_str(DEFAULT_ALACRITTY_CONFIG).expect("deserialize config"); let old_dynamic_title = config.dynamic_title; let options = Options::default(); let config = config.update_dynamic_title(&options); @@ -2672,8 +2693,8 @@ mod tests { #[test] fn dynamic_title_overridden_by_options() { - let config: Config = ::serde_yaml::from_str(DEFAULT_ALACRITTY_CONFIG) - .expect("deserialize config"); + let config: Config = + ::serde_yaml::from_str(DEFAULT_ALACRITTY_CONFIG).expect("deserialize config"); let mut options = Options::default(); options.title = Some("foo".to_owned()); let config = config.update_dynamic_title(&options); diff --git a/src/display.rs b/src/display.rs index 8266e65..8dca2f6 100644 --- a/src/display.rs +++ b/src/display.rs @@ -14,24 +14,24 @@ //! The display subsystem including window management, font rasterization, and //! GPU drawing. -use std::sync::mpsc; use std::f64; +use std::sync::mpsc; -use parking_lot::MutexGuard; use glutin::dpi::{PhysicalPosition, PhysicalSize}; +use parking_lot::MutexGuard; use crate::cli; use crate::config::Config; -use font::{self, Rasterize}; -use crate::meter::Meter; -use crate::renderer::{self, GlyphCache, QuadRenderer}; -use crate::renderer::rects::{Rects, Rect}; -use crate::term::{Term, SizeInfo, RenderableCell}; -use crate::sync::FairMutex; -use crate::window::{self, Window}; -use crate::term::color::Rgb; use crate::index::Line; use crate::message_bar::Message; +use crate::meter::Meter; +use crate::renderer::rects::{Rect, Rects}; +use crate::renderer::{self, GlyphCache, QuadRenderer}; +use crate::sync::FairMutex; +use crate::term::color::Rgb; +use crate::term::{RenderableCell, SizeInfo, Term}; +use crate::window::{self, Window}; +use font::{self, Rasterize}; #[derive(Debug)] pub enum Error { @@ -152,8 +152,8 @@ impl Display { info!("Device pixel ratio: {}", dpr); // get window properties for initializing the other subsystems - let mut viewport_size = window.inner_size_pixels() - .expect("glutin returns window size").to_physical(dpr); + let mut viewport_size = + window.inner_size_pixels().expect("glutin returns window size").to_physical(dpr); // Create renderer let mut renderer = QuadRenderer::new(viewport_size)?; @@ -161,8 +161,7 @@ impl Display { let (glyph_cache, cell_width, cell_height) = Self::new_glyph_cache(dpr, &mut renderer, config)?; - let dimensions = options.dimensions() - .unwrap_or_else(|| config.dimensions()); + let dimensions = options.dimensions().unwrap_or_else(|| config.dimensions()); let mut padding_x = f64::from(config.padding().x) * dpr; let mut padding_y = f64::from(config.padding().y) * dpr; @@ -216,13 +215,9 @@ impl Display { // Clear screen let background_color = config.colors().primary.background; - renderer.with_api( - config, - &size_info, - |api| { - api.clear(background_color); - }, - ); + renderer.with_api(config, &size_info, |api| { + api.clear(background_color); + }); Ok(Display { window, @@ -238,9 +233,11 @@ impl Display { }) } - fn new_glyph_cache(dpr: f64, renderer: &mut QuadRenderer, config: &Config) - -> Result<(GlyphCache, f32, f32), Error> - { + fn new_glyph_cache( + dpr: f64, + renderer: &mut QuadRenderer, + config: &Config, + ) -> Result<(GlyphCache, f32, f32), Error> { let font = config.font().clone(); let rasterizer = font::Rasterizer::new(dpr as f32, config.use_thin_strokes())?; @@ -253,8 +250,7 @@ impl Display { renderer.with_loader(|mut api| GlyphCache::new(rasterizer, &font, &mut api))?; let stop = init_start.elapsed(); - let stop_f = stop.as_secs() as f64 + - f64::from(stop.subsec_nanos()) / 1_000_000_000f64; + let stop_f = stop.as_secs() as f64 + f64::from(stop.subsec_nanos()) / 1_000_000_000f64; info!("... finished initializing glyph cache in {}s", stop_f); cache @@ -322,8 +318,8 @@ impl Display { let dpr = self.window.hidpi_factor(); // Font size/DPI factor modification detected - let font_changed = terminal.font_size != self.font_size - || (dpr - self.size_info.dpr).abs() > f64::EPSILON; + let font_changed = + terminal.font_size != self.font_size || (dpr - self.size_info.dpr).abs() > f64::EPSILON; if font_changed || self.last_message != terminal.message_buffer_mut().message() { if new_size == None { @@ -391,9 +387,8 @@ impl Display { let background_color = terminal.background_color(); let window_focused = self.window.is_focused; - let grid_cells: Vec = terminal - .renderable_cells(config, window_focused) - .collect(); + let grid_cells: Vec = + terminal.renderable_cells(config, window_focused).collect(); // Get message from terminal to ignore modifications after lock is dropped let message_buffer = terminal.message_buffer_mut().message(); @@ -486,20 +481,14 @@ impl Display { // Draw render timer if self.render_timer { let timing = format!("{:.3} usec", self.meter.average()); - let color = Rgb { - r: 0xd5, - g: 0x4e, - b: 0x53, - }; + let color = Rgb { r: 0xd5, g: 0x4e, b: 0x53 }; self.renderer.with_api(config, &size_info, |mut api| { api.render_string(&timing[..], size_info.lines() - 2, glyph_cache, Some(color)); }); } } - self.window - .swap_buffers() - .expect("swap buffers"); + self.window.swap_buffers().expect("swap buffers"); } pub fn get_window_id(&self) -> Option { @@ -509,13 +498,8 @@ impl Display { /// Adjust the IME editor position according to the new location of the cursor pub fn update_ime_position(&mut self, terminal: &Term) { let point = terminal.cursor().point; - let SizeInfo { - cell_width: cw, - cell_height: ch, - padding_x: px, - padding_y: py, - .. - } = *terminal.size_info(); + let SizeInfo { cell_width: cw, cell_height: ch, padding_x: px, padding_y: py, .. } = + *terminal.size_info(); let dpr = self.window().hidpi_factor(); let nspot_x = f64::from(px + point.col.0 as f32 * cw); diff --git a/src/event.rs b/src/event.rs index f7d9f22..ffedce2 100644 --- a/src/event.rs +++ b/src/event.rs @@ -1,33 +1,33 @@ //! Process window events +use std::borrow::Cow; +use std::env; #[cfg(unix)] use std::fs; -use std::borrow::Cow; use std::fs::File; use std::io::Write; use std::sync::mpsc; -use std::time::{Instant}; -use std::env; +use std::time::Instant; -use serde_json as json; -use parking_lot::MutexGuard; -use glutin::{self, ModifiersState, Event, ElementState, MouseButton}; -use copypasta::{Clipboard, Load, Store, Buffer as ClipboardBuffer}; +use copypasta::{Buffer as ClipboardBuffer, Clipboard, Load, Store}; use glutin::dpi::PhysicalSize; +use glutin::{self, ElementState, Event, ModifiersState, MouseButton}; +use parking_lot::MutexGuard; +use serde_json as json; -#[cfg(unix)] -use crate::tty; -use crate::grid::Scroll; -use crate::config::{self, Config}; use crate::cli::Options; +use crate::config::{self, Config}; use crate::display::OnResize; -use crate::index::{Line, Column, Side, Point}; -use crate::input::{self, MouseBinding, KeyBinding}; +use crate::grid::Scroll; +use crate::index::{Column, Line, Point, Side}; +use crate::input::{self, KeyBinding, MouseBinding}; use crate::selection::Selection; use crate::sync::FairMutex; -use crate::term::{Term, SizeInfo}; use crate::term::cell::Cell; -use crate::util::{limit, start_daemon}; +use crate::term::{SizeInfo, Term}; +#[cfg(unix)] +use crate::tty; use crate::util::fmt::Red; +use crate::util::{limit, start_daemon}; use crate::window::Window; /// Byte sequences are sent to a `Notify` in response to some events @@ -66,10 +66,7 @@ impl<'a, N: Notify + 'a> input::ActionContext for ActionContext<'a, N> { let size_info = self.size_info(); let point = size_info.pixels_to_coords(x, y); let cell_side = self.mouse().cell_side; - self.update_selection(Point { - line: point.line, - col: point.col - }, cell_side); + self.update_selection(Point { line: point.line, col: point.col }, cell_side); } } @@ -209,9 +206,7 @@ impl WindowChanges { impl Default for WindowChanges { fn default() -> WindowChanges { - WindowChanges { - hide: false, - } + WindowChanges { hide: false } } } @@ -358,16 +353,14 @@ impl Processor { grid.initialize_all(&Cell::default()); grid.truncate(); - let serialized_grid = json::to_string(&grid) - .expect("serialize grid"); + let serialized_grid = json::to_string(&grid).expect("serialize grid"); - let serialized_size = json::to_string(processor.ctx.terminal.size_info()) - .expect("serialize size"); + let serialized_size = + json::to_string(processor.ctx.terminal.size_info()) + .expect("serialize size"); - let serialized_config = format!( - "{{\"history_size\":{}}}", - grid.history_size() - ); + let serialized_config = + format!("{{\"history_size\":{}}}", grid.history_size()); File::create("./grid.json") .and_then(|mut f| f.write_all(serialized_grid.as_bytes())) @@ -453,7 +446,7 @@ impl Processor { }, Event::Awakened => { processor.ctx.terminal.dirty = true; - } + }, } } @@ -462,7 +455,7 @@ impl Processor { pub fn process_events<'a>( &mut self, term: &'a FairMutex, - window: &mut Window + window: &mut Window, ) -> MutexGuard<'a, Term> { // Terminal is lazily initialized the first time an event is returned // from the blocking WaitEventsIterator. Otherwise, the pty reader would diff --git a/src/event_loop.rs b/src/event_loop.rs index 31e803d..4941b47 100644 --- a/src/event_loop.rs +++ b/src/event_loop.rs @@ -1,10 +1,10 @@ //! The main event loop which performs I/O on the pseudoterminal use std::borrow::Cow; use std::collections::VecDeque; -use std::io::{self, ErrorKind, Read, Write}; use std::fs::File; -use std::sync::Arc; +use std::io::{self, ErrorKind, Read, Write}; use std::marker::Send; +use std::sync::Arc; use mio::{self, Events, PollOpt, Ready}; use mio_extras::channel::{self, Receiver, Sender}; @@ -15,10 +15,10 @@ use mio::unix::UnixReady; use crate::ansi; use crate::display; use crate::event; -use crate::tty; -use crate::term::Term; -use crate::util::thread; use crate::sync::FairMutex; +use crate::term::Term; +use crate::tty; +use crate::util::thread; /// Messages that may be sent to the `EventLoop` #[derive(Debug)] @@ -58,14 +58,14 @@ enum DrainResult { /// Nothing was available to receive Empty, /// A shutdown message was received - Shutdown + Shutdown, } impl DrainResult { pub fn is_shutdown(&self) -> bool { match *self { DrainResult::Shutdown => true, - _ => false + _ => false, } } } @@ -84,12 +84,13 @@ pub struct Notifier(pub Sender); impl event::Notify for Notifier { fn notify(&mut self, bytes: B) - where B: Into>, + where + B: Into>, { let bytes = bytes.into(); // terminal hangs if we send 0 bytes through. if bytes.len() == 0 { - return + return; } if self.0.send(Msg::Input(bytes)).is_err() { panic!("expected send event loop msg"); @@ -99,11 +100,7 @@ impl event::Notify for Notifier { impl Default for State { fn default() -> State { - State { - write_list: VecDeque::new(), - parser: ansi::Processor::new(), - writing: None, - } + State { write_list: VecDeque::new(), parser: ansi::Processor::new(), writing: None } } } @@ -117,9 +114,7 @@ impl State { #[inline] fn goto_next(&mut self) { - self.writing = self.write_list - .pop_front() - .map(Writing::new); + self.writing = self.write_list.pop_front().map(Writing::new); } #[inline] @@ -161,8 +156,8 @@ impl Writing { } impl EventLoop - where - T: tty::EventedPty + Send + 'static, +where + T: tty::EventedPty + Send + 'static, { /// Create a new event loop pub fn new( @@ -198,10 +193,10 @@ impl EventLoop match msg { Msg::Input(input) => { state.write_list.push_back(input); - } + }, Msg::Shutdown => { return DrainResult::Shutdown; - } + }, } } @@ -233,8 +228,8 @@ impl EventLoop buf: &mut [u8], mut writer: Option<&mut X>, ) -> io::Result<()> - where - X: Write, + where + X: Write, { const MAX_READ: usize = 0x1_0000; let mut processed = 0; @@ -271,20 +266,18 @@ impl EventLoop // Run the parser for byte in &buf[..got] { - state - .parser - .advance(&mut **terminal, *byte, &mut self.pty.writer()); + state.parser.advance(&mut **terminal, *byte, &mut self.pty.writer()); } // Exit if we've processed enough bytes if processed > MAX_READ { break; } - } + }, Err(err) => match err.kind() { ErrorKind::Interrupted | ErrorKind::WouldBlock => { break; - } + }, _ => return Err(err), }, } @@ -311,21 +304,21 @@ impl EventLoop Ok(0) => { state.set_current(Some(current)); break 'write_many; - } + }, Ok(n) => { current.advance(n); if current.finished() { state.goto_next(); break 'write_one; } - } + }, Err(err) => { state.set_current(Some(current)); match err.kind() { ErrorKind::Interrupted | ErrorKind::WouldBlock => break 'write_many, _ => return Err(err), } - } + }, } } } @@ -343,14 +336,10 @@ impl EventLoop let poll_opts = PollOpt::edge() | PollOpt::oneshot(); let channel_token = tokens.next().unwrap(); - self.poll - .register(&self.rx, channel_token, Ready::readable(), poll_opts) - .unwrap(); + self.poll.register(&self.rx, channel_token, Ready::readable(), poll_opts).unwrap(); // Register TTY through EventedRW interface - self.pty - .register(&self.poll, &mut tokens, Ready::readable(), poll_opts) - .unwrap(); + self.pty.register(&self.poll, &mut tokens, Ready::readable(), poll_opts).unwrap(); let mut events = Events::with_capacity(1024); @@ -385,8 +374,12 @@ impl EventLoop } }, - token if token == self.pty.read_token() || token == self.pty.write_token() => { - #[cfg(unix)] { + token + if token == self.pty.read_token() + || token == self.pty.write_token() => + { + #[cfg(unix)] + { if UnixReady::from(event.readiness()).is_hup() { // don't try to do I/O on a dead PTY continue; @@ -395,7 +388,8 @@ impl EventLoop if event.readiness().is_readable() { if let Err(e) = self.pty_read(&mut state, &mut buf, pipe.as_mut()) { - #[cfg(target_os = "linux")] { + #[cfg(target_os = "linux")] + { // On Linux, a `read` on the master side of a PTY can fail // with `EIO` if the client side hangs up. In that case, // just loop back round for the inevitable `Exited` event. diff --git a/src/grid/mod.rs b/src/grid/mod.rs index a190353..3a6bacf 100644 --- a/src/grid/mod.rs +++ b/src/grid/mod.rs @@ -14,10 +14,10 @@ //! A specialized 2d grid implementation optimized for use in a terminal. -use std::cmp::{min, max, Ordering}; -use std::ops::{Deref, Range, Index, IndexMut, RangeTo, RangeFrom, RangeFull, RangeInclusive}; +use std::cmp::{max, min, Ordering}; +use std::ops::{Deref, Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo}; -use crate::index::{self, Point, Line, Column, IndexRange}; +use crate::index::{self, Column, IndexRange, Line, Point}; use crate::selection::Selection; mod row; @@ -55,13 +55,13 @@ impl Deref for Indexed { impl ::std::cmp::PartialEq for Grid { fn eq(&self, other: &Self) -> bool { // Compare struct fields and check result of grid comparison - self.raw.eq(&other.raw) && - self.cols.eq(&other.cols) && - self.lines.eq(&other.lines) && - self.display_offset.eq(&other.display_offset) && - self.scroll_limit.eq(&other.scroll_limit) && - self.selection.eq(&other.selection) && - self.url_highlight.eq(&other.url_highlight) + self.raw.eq(&other.raw) + && self.cols.eq(&other.cols) + && self.lines.eq(&other.lines) + && self.display_offset.eq(&other.display_offset) + && self.scroll_limit.eq(&other.scroll_limit) + && self.selection.eq(&other.selection) + && self.url_highlight.eq(&other.url_highlight) } } @@ -142,10 +142,7 @@ impl Grid { } pub fn visible_to_buffer(&self, point: Point) -> Point { - Point { - line: self.visible_line_to_buffer(point.line), - col: point.col - } + Point { line: self.visible_line_to_buffer(point.line), col: point.col } } pub fn buffer_line_to_visible(&self, line: usize) -> ViewportPosition { @@ -164,8 +161,7 @@ impl Grid { } /// Update the size of the scrollback history - pub fn update_history(&mut self, history_size: usize, template: &T) - { + pub fn update_history(&mut self, history_size: usize, template: &T) { self.raw.update_history(history_size, Row::new(self.cols, &template)); self.max_scroll_limit = history_size; self.scroll_limit = min(self.scroll_limit, history_size); @@ -177,20 +173,14 @@ impl Grid { Scroll::Lines(count) => { self.display_offset = min( max((self.display_offset as isize) + count, 0isize) as usize, - self.scroll_limit + self.scroll_limit, ); }, Scroll::PageUp => { - self.display_offset = min( - self.display_offset + self.lines.0, - self.scroll_limit - ); + self.display_offset = min(self.display_offset + self.lines.0, self.scroll_limit); }, Scroll::PageDown => { - self.display_offset -= min( - self.display_offset, - self.lines.0 - ); + self.display_offset -= min(self.display_offset, self.lines.0); }, Scroll::Top => self.display_offset = self.scroll_limit, Scroll::Bottom => self.display_offset = 0, @@ -222,8 +212,7 @@ impl Grid { } } - fn increase_scroll_limit(&mut self, count: usize, template: &T) - { + fn increase_scroll_limit(&mut self, count: usize, template: &T) { self.scroll_limit = min(self.scroll_limit + count, self.max_scroll_limit); // Initialize new lines when the history buffer is smaller than the scroll limit @@ -246,11 +235,7 @@ impl Grid { /// Alacritty keeps the cursor at the bottom of the terminal as long as there /// is scrollback available. Once scrollback is exhausted, new lines are /// simply added to the bottom of the screen. - fn grow_lines( - &mut self, - new_line_count: index::Line, - template: &T, - ) { + fn grow_lines(&mut self, new_line_count: index::Line, template: &T) { let lines_added = new_line_count - self.lines; // Need to "resize" before updating buffer @@ -435,7 +420,7 @@ impl Grid { // Now, restore any scroll region lines let lines = self.lines; - for i in IndexRange(region.end .. lines) { + for i in IndexRange(region.end..lines) { self.raw.swap_lines(i, i + positions); } @@ -449,7 +434,7 @@ impl Grid { self.raw.swap_lines(line, line - positions); } - for line in IndexRange(region.start .. (region.start + positions)) { + for line in IndexRange(region.start..(region.start + positions)) { self.raw[line].reset(&template); } } @@ -458,19 +443,12 @@ impl Grid { /// scroll_up moves lines at the bottom towards the top /// /// This is the performance-sensitive part of scrolling. - pub fn scroll_up( - &mut self, - region: &Range, - positions: index::Line, - template: &T - ) { + pub fn scroll_up(&mut self, region: &Range, positions: index::Line, template: &T) { if region.start == Line(0) { // Update display offset when not pinned to active area if self.display_offset != 0 { - self.display_offset = min( - self.display_offset + *positions, - self.len() - self.num_lines().0, - ); + self.display_offset = + min(self.display_offset + *positions, self.len() - self.num_lines().0); } self.increase_scroll_limit(*positions, template); @@ -506,7 +484,7 @@ impl Grid { } // Clear reused lines - for line in IndexRange((region.end - positions) .. region.end) { + for line in IndexRange((region.end - positions)..region.end) { self.raw[line].reset(&template); } } @@ -569,7 +547,7 @@ impl Grid { /// This is used only for initializing after loading ref-tests pub fn initialize_all(&mut self, template: &T) where - T: Copy + T: Copy, { let history_size = self.raw.len().saturating_sub(*self.lines); self.raw.initialize(self.max_scroll_limit - history_size, Row::new(self.cols, template)); @@ -581,10 +559,7 @@ impl Grid { } pub fn iter_from(&self, point: Point) -> GridIterator<'_, T> { - GridIterator { - grid: self, - cur: point, - } + GridIterator { grid: self, cur: point } } #[inline] @@ -613,8 +588,7 @@ impl<'a, T> Iterator for GridIterator<'a, T> { let last_col = self.grid.num_cols() - Column(1); match self.cur { Point { line, col } if line == 0 && col == last_col => None, - Point { col, .. } if - (col == last_col) => { + Point { col, .. } if (col == last_col) => { self.cur.line -= 1; self.cur.col = Column(0); Some(&self.grid[self.cur.line][self.cur.col]) @@ -622,7 +596,7 @@ impl<'a, T> Iterator for GridIterator<'a, T> { _ => { self.cur.col += Column(1); Some(&self.grid[self.cur.line][self.cur.col]) - } + }, } } } @@ -641,7 +615,7 @@ impl<'a, T> BidirectionalIterator for GridIterator<'a, T> { _ => { self.cur.col -= Column(1); Some(&self.grid[self.cur.line][self.cur.col]) - } + }, } } } @@ -742,77 +716,48 @@ impl IndexRegion, T> for Grid { assert!(index.start < self.num_lines()); assert!(index.end <= self.num_lines()); assert!(index.start <= index.end); - Region { - start: index.start, - end: index.end, - raw: &self.raw - } + Region { start: index.start, end: index.end, raw: &self.raw } } + fn region_mut(&mut self, index: Range) -> RegionMut<'_, T> { assert!(index.start < self.num_lines()); assert!(index.end <= self.num_lines()); assert!(index.start <= index.end); - RegionMut { - start: index.start, - end: index.end, - raw: &mut self.raw - } + RegionMut { start: index.start, end: index.end, raw: &mut self.raw } } } impl IndexRegion, T> for Grid { fn region(&self, index: RangeTo) -> Region<'_, T> { assert!(index.end <= self.num_lines()); - Region { - start: Line(0), - end: index.end, - raw: &self.raw - } + Region { start: Line(0), end: index.end, raw: &self.raw } } + fn region_mut(&mut self, index: RangeTo) -> RegionMut<'_, T> { assert!(index.end <= self.num_lines()); - RegionMut { - start: Line(0), - end: index.end, - raw: &mut self.raw - } + RegionMut { start: Line(0), end: index.end, raw: &mut self.raw } } } impl IndexRegion, T> for Grid { fn region(&self, index: RangeFrom) -> Region<'_, T> { assert!(index.start < self.num_lines()); - Region { - start: index.start, - end: self.num_lines(), - raw: &self.raw - } + Region { start: index.start, end: self.num_lines(), raw: &self.raw } } + fn region_mut(&mut self, index: RangeFrom) -> RegionMut<'_, T> { assert!(index.start < self.num_lines()); - RegionMut { - start: index.start, - end: self.num_lines(), - raw: &mut self.raw - } + RegionMut { start: index.start, end: self.num_lines(), raw: &mut self.raw } } } impl IndexRegion for Grid { fn region(&self, _: RangeFull) -> Region<'_, T> { - Region { - start: Line(0), - end: self.num_lines(), - raw: &self.raw - } + Region { start: Line(0), end: self.num_lines(), raw: &self.raw } } fn region_mut(&mut self, _: RangeFull) -> RegionMut<'_, T> { - RegionMut { - start: Line(0), - end: self.num_lines(), - raw: &mut self.raw - } + RegionMut { start: Line(0), end: self.num_lines(), raw: &mut self.raw } } } @@ -829,33 +774,26 @@ pub struct RegionIterMut<'a, T> { } impl<'a, T> IntoIterator for Region<'a, T> { - type Item = &'a Row; type IntoIter = RegionIter<'a, T>; + type Item = &'a Row; fn into_iter(self) -> Self::IntoIter { - RegionIter { - end: self.end, - cur: self.start, - raw: self.raw - } + RegionIter { end: self.end, cur: self.start, raw: self.raw } } } impl<'a, T> IntoIterator for RegionMut<'a, T> { - type Item = &'a mut Row; type IntoIter = RegionIterMut<'a, T>; + type Item = &'a mut Row; fn into_iter(self) -> Self::IntoIter { - RegionIterMut { - end: self.end, - cur: self.start, - raw: self.raw - } + RegionIterMut { end: self.end, cur: self.start, raw: self.raw } } } impl<'a, T> Iterator for RegionIter<'a, T> { type Item = &'a Row; + fn next(&mut self) -> Option { if self.cur < self.end { let index = self.cur; @@ -869,13 +807,12 @@ impl<'a, T> Iterator for RegionIter<'a, T> { impl<'a, T> Iterator for RegionIterMut<'a, T> { type Item = &'a mut Row; + fn next(&mut self) -> Option { if self.cur < self.end { let index = self.cur; self.cur += 1; - unsafe { - Some(&mut *(&mut self.raw[index] as *mut _)) - } + unsafe { Some(&mut *(&mut self.raw[index] as *mut _)) } } else { None } @@ -898,7 +835,7 @@ pub struct DisplayIter<'a, T> { impl<'a, T: 'a> DisplayIter<'a, T> { pub fn new(grid: &'a Grid) -> DisplayIter<'a, T> { let offset = grid.display_offset + *grid.num_lines() - 1; - let limit = grid.display_offset; + let limit = grid.display_offset; let col = Column(0); let line = Line(0); @@ -932,7 +869,7 @@ impl<'a, T: Copy + 'a> Iterator for DisplayIter<'a, T> { let item = Some(Indexed { inner: self.grid.raw[self.offset][self.col], line: self.line, - column: self.col + column: self.col, }); // Update line/col to point to next item diff --git a/src/grid/row.rs b/src/grid/row.rs index ef27f04..0a58de9 100644 --- a/src/grid/row.rs +++ b/src/grid/row.rs @@ -14,9 +14,9 @@ //! Defines the Row type which makes up lines in the grid +use std::cmp::{max, min}; use std::ops::{Index, IndexMut}; -use std::ops::{Range, RangeTo, RangeFrom, RangeFull, RangeToInclusive}; -use std::cmp::{min, max}; +use std::ops::{Range, RangeFrom, RangeFull, RangeTo, RangeToInclusive}; use std::slice; use crate::grid::GridCell; @@ -46,10 +46,7 @@ impl PartialEq for Row { impl Row { pub fn new(columns: Column, template: &T) -> Row { - Row { - inner: vec![*template; *columns], - occ: 0, - } + Row { inner: vec![*template; *columns], occ: 0 } } pub fn grow(&mut self, cols: Column, template: &T) { @@ -62,7 +59,7 @@ impl Row { pub fn shrink(&mut self, cols: Column) -> Option> where - T: GridCell + T: GridCell, { if self.inner.len() <= cols.0 { return None; @@ -96,10 +93,7 @@ impl Row { impl Row { #[inline] pub fn from_vec(vec: Vec, occ: usize) -> Row { - Row { - inner: vec, - occ, - } + Row { inner: vec, occ } } #[inline] @@ -121,7 +115,7 @@ impl Row { #[inline] pub fn append(&mut self, vec: &mut Vec) where - T: GridCell + T: GridCell, { self.inner.append(vec); self.occ = self.inner.iter().rposition(|c| !c.is_empty()).map(|i| i + 1).unwrap_or(0); @@ -137,7 +131,7 @@ impl Row { #[inline] pub fn is_empty(&self) -> bool where - T: GridCell + T: GridCell, { self.inner.iter().all(|c| c.is_empty()) } @@ -153,8 +147,8 @@ impl Row { } impl<'a, T> IntoIterator for &'a mut Row { - type Item = &'a mut T; type IntoIter = slice::IterMut<'a, T>; + type Item = &'a mut T; #[inline] fn into_iter(self) -> slice::IterMut<'a, T> { diff --git a/src/grid/storage.rs b/src/grid/storage.rs index 6a119ea..3226042 100644 --- a/src/grid/storage.rs +++ b/src/grid/storage.rs @@ -15,9 +15,9 @@ use std::ops::{Index, IndexMut}; use static_assertions::assert_eq_size; -use crate::index::{Column, Line}; -use crate::grid::GridCell; use super::Row; +use crate::grid::GridCell; +use crate::index::{Column, Line}; /// Maximum number of invisible lines before buffer is resized const TRUNCATE_STEP: usize = 100; @@ -46,11 +46,8 @@ impl ::std::cmp::PartialEq for Storage { } // Check which vec has the bigger zero - let (ref bigger, ref smaller) = if self.zero >= other.zero { - (self, other) - } else { - (other, self) - }; + let (ref bigger, ref smaller) = + if self.zero >= other.zero { (self, other) } else { (other, self) }; // Calculate the actual zero offset let len = self.inner.len(); @@ -88,12 +85,7 @@ impl Storage { // Initialize visible lines, the scrollback buffer is initialized dynamically let inner = vec![template; lines.0]; - Storage { - inner, - zero: 0, - visible_lines: lines - 1, - len: lines.0, - } + Storage { inner, zero: 0, visible_lines: lines - 1, len: lines.0 } } /// Update the size of the scrollback history @@ -179,7 +171,8 @@ impl Storage { /// Dynamically grow the storage buffer at runtime pub fn initialize(&mut self, num_rows: usize, template_row: Row) - where T: Clone + where + T: Clone, { let mut new = vec![template_row; num_rows]; @@ -297,7 +290,7 @@ impl Storage { #[inline] pub fn shrink_hidden(&mut self, cols: Column) where - T: GridCell + Copy + T: GridCell + Copy, { let start = self.zero + self.len; let end = self.zero + self.inner.len(); @@ -317,7 +310,7 @@ impl Storage { #[inline] pub fn grow_hidden(&mut self, cols: Column, template: &T) where - T: Copy + Clone + T: Copy + Clone, { let start = self.zero + self.len; let end = self.zero + self.inner.len(); @@ -333,6 +326,7 @@ impl Storage { impl Index for Storage { type Output = Row; + #[inline] fn index(&self, index: usize) -> &Self::Output { &self.inner[self.compute_index(index)] @@ -349,6 +343,7 @@ impl IndexMut for Storage { impl Index for Storage { type Output = Row; + #[inline] fn index(&self, index: Line) -> &Self::Output { let index = self.visible_lines - index; @@ -379,7 +374,11 @@ impl IndexMut for Storage { fn grow_after_zero() { // Setup storage area let mut storage = Storage { - inner: vec![Row::new(Column(1), &'0'), Row::new(Column(1), &'1'), Row::new(Column(1), &'-')], + inner: vec![ + Row::new(Column(1), &'0'), + Row::new(Column(1), &'1'), + Row::new(Column(1), &'-'), + ], zero: 0, visible_lines: Line(2), len: 3, @@ -390,7 +389,12 @@ fn grow_after_zero() { // Make sure the result is correct let expected = Storage { - inner: vec![Row::new(Column(1), &'-'), Row::new(Column(1), &'0'), Row::new(Column(1), &'1'), Row::new(Column(1), &'-')], + inner: vec![ + Row::new(Column(1), &'-'), + Row::new(Column(1), &'0'), + Row::new(Column(1), &'1'), + Row::new(Column(1), &'-'), + ], zero: 1, visible_lines: Line(0), len: 4, @@ -415,7 +419,11 @@ fn grow_after_zero() { fn grow_before_zero() { // Setup storage area let mut storage = Storage { - inner: vec![Row::new(Column(1), &'-'), Row::new(Column(1), &'0'), Row::new(Column(1), &'1')], + inner: vec![ + Row::new(Column(1), &'-'), + Row::new(Column(1), &'0'), + Row::new(Column(1), &'1'), + ], zero: 1, visible_lines: Line(2), len: 3, @@ -426,7 +434,12 @@ fn grow_before_zero() { // Make sure the result is correct let expected = Storage { - inner: vec![Row::new(Column(1), &'-'), Row::new(Column(1), &'-'), Row::new(Column(1), &'0'), Row::new(Column(1), &'1')], + inner: vec![ + Row::new(Column(1), &'-'), + Row::new(Column(1), &'-'), + Row::new(Column(1), &'0'), + Row::new(Column(1), &'1'), + ], zero: 2, visible_lines: Line(0), len: 4, @@ -450,7 +463,11 @@ fn grow_before_zero() { fn shrink_before_zero() { // Setup storage area let mut storage = Storage { - inner: vec![Row::new(Column(1), &'2'), Row::new(Column(1), &'0'), Row::new(Column(1), &'1')], + inner: vec![ + Row::new(Column(1), &'2'), + Row::new(Column(1), &'0'), + Row::new(Column(1), &'1'), + ], zero: 1, visible_lines: Line(2), len: 3, @@ -461,7 +478,11 @@ fn shrink_before_zero() { // Make sure the result is correct let expected = Storage { - inner: vec![Row::new(Column(1), &'2'), Row::new(Column(1), &'0'), Row::new(Column(1), &'1')], + inner: vec![ + Row::new(Column(1), &'2'), + Row::new(Column(1), &'0'), + Row::new(Column(1), &'1'), + ], zero: 1, visible_lines: Line(0), len: 2, @@ -485,7 +506,11 @@ fn shrink_before_zero() { fn shrink_after_zero() { // Setup storage area let mut storage = Storage { - inner: vec![Row::new(Column(1), &'0'), Row::new(Column(1), &'1'), Row::new(Column(1), &'2')], + inner: vec![ + Row::new(Column(1), &'0'), + Row::new(Column(1), &'1'), + Row::new(Column(1), &'2'), + ], zero: 0, visible_lines: Line(2), len: 3, @@ -496,7 +521,11 @@ fn shrink_after_zero() { // Make sure the result is correct let expected = Storage { - inner: vec![Row::new(Column(1), &'0'), Row::new(Column(1), &'1'), Row::new(Column(1), &'2')], + inner: vec![ + Row::new(Column(1), &'0'), + Row::new(Column(1), &'1'), + Row::new(Column(1), &'2'), + ], zero: 0, visible_lines: Line(0), len: 2, @@ -526,7 +555,14 @@ fn shrink_after_zero() { fn shrink_before_and_after_zero() { // Setup storage area let mut storage = Storage { - inner: vec![Row::new(Column(1), &'4'), Row::new(Column(1), &'5'), Row::new(Column(1), &'0'), Row::new(Column(1), &'1'), Row::new(Column(1), &'2'), Row::new(Column(1), &'3')], + inner: vec![ + Row::new(Column(1), &'4'), + Row::new(Column(1), &'5'), + Row::new(Column(1), &'0'), + Row::new(Column(1), &'1'), + Row::new(Column(1), &'2'), + Row::new(Column(1), &'3'), + ], zero: 2, visible_lines: Line(5), len: 6, @@ -537,7 +573,14 @@ fn shrink_before_and_after_zero() { // Make sure the result is correct let expected = Storage { - inner: vec![Row::new(Column(1), &'4'), Row::new(Column(1), &'5'), Row::new(Column(1), &'0'), Row::new(Column(1), &'1'), Row::new(Column(1), &'2'), Row::new(Column(1), &'3')], + inner: vec![ + Row::new(Column(1), &'4'), + Row::new(Column(1), &'5'), + Row::new(Column(1), &'0'), + Row::new(Column(1), &'1'), + Row::new(Column(1), &'2'), + Row::new(Column(1), &'3'), + ], zero: 2, visible_lines: Line(0), len: 2, @@ -563,7 +606,14 @@ fn shrink_before_and_after_zero() { fn truncate_invisible_lines() { // Setup storage area let mut storage = Storage { - inner: vec![Row::new(Column(1), &'4'), Row::new(Column(1), &'5'), Row::new(Column(1), &'0'), Row::new(Column(1), &'1'), Row::new(Column(1), &'2'), Row::new(Column(1), &'3')], + inner: vec![ + Row::new(Column(1), &'4'), + Row::new(Column(1), &'5'), + Row::new(Column(1), &'0'), + Row::new(Column(1), &'1'), + Row::new(Column(1), &'2'), + Row::new(Column(1), &'3'), + ], zero: 2, visible_lines: Line(1), len: 2, @@ -598,7 +648,11 @@ fn truncate_invisible_lines() { fn truncate_invisible_lines_beginning() { // Setup storage area let mut storage = Storage { - inner: vec![Row::new(Column(1), &'1'), Row::new(Column(1), &'2'), Row::new(Column(1), &'0')], + inner: vec![ + Row::new(Column(1), &'1'), + Row::new(Column(1), &'2'), + Row::new(Column(1), &'0'), + ], zero: 2, visible_lines: Line(1), len: 2, diff --git a/src/grid/tests.rs b/src/grid/tests.rs index 82edda6..fc41fdc 100644 --- a/src/grid/tests.rs +++ b/src/grid/tests.rs @@ -14,10 +14,10 @@ //! Tests for the Gird -use super::{Grid, BidirectionalIterator}; -use crate::index::{Point, Line, Column}; -use crate::term::cell::{Cell, Flags}; +use super::{BidirectionalIterator, Grid}; use crate::grid::GridCell; +use crate::index::{Column, Line, Point}; +use crate::term::cell::{Cell, Flags}; impl GridCell for usize { fn is_empty(&self) -> bool { @@ -101,14 +101,11 @@ fn test_iter() { let mut grid = Grid::new(Line(5), Column(5), 0, 0); for i in 0..5 { for j in 0..5 { - grid[Line(i)][Column(j)] = i*5 + j; + grid[Line(i)][Column(j)] = i * 5 + j; } } - let mut iter = grid.iter_from(Point { - line: 4, - col: Column(0), - }); + let mut iter = grid.iter_from(Point { line: 4, col: Column(0) }); assert_eq!(None, iter.prev()); assert_eq!(Some(&1), iter.next()); @@ -128,12 +125,8 @@ fn test_iter() { assert_eq!(Column(4), iter.cur.col); assert_eq!(4, iter.cur.line); - // test that iter ends at end of grid - let mut final_iter = grid.iter_from(Point { - line: 0, - col: Column(4), - }); + let mut final_iter = grid.iter_from(Point { line: 0, col: Column(4) }); assert_eq!(None, final_iter.next()); assert_eq!(Some(&23), final_iter.prev()); } diff --git a/src/index.rs b/src/index.rs index 0004454..0351c0e 100644 --- a/src/index.rs +++ b/src/index.rs @@ -17,18 +17,18 @@ /// Indexing types and implementations for Grid and Line use std::cmp::{Ord, Ordering}; use std::fmt; -use std::ops::{self, Deref, Range, RangeInclusive, Add, Sub, AddAssign, SubAssign}; +use std::ops::{self, Add, AddAssign, Deref, Range, RangeInclusive, Sub, SubAssign}; /// The side of a cell #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub enum Side { Left, - Right + Right, } /// Index in the grid using row, column notation #[derive(Debug, Clone, Copy, Default, Eq, PartialEq, Serialize, Deserialize, PartialOrd)] -pub struct Point { +pub struct Point { pub line: L, pub col: Column, } @@ -43,11 +43,10 @@ impl Ord for Point { fn cmp(&self, other: &Point) -> Ordering { use std::cmp::Ordering::*; match (self.line.cmp(&other.line), self.col.cmp(&other.col)) { - (Equal, Equal) => Equal, - (Equal, ord) | - (ord, Equal) => ord, - (Less, _) => Less, - (Greater, _) => Greater, + (Equal, Equal) => Equal, + (Equal, ord) | (ord, Equal) => ord, + (Less, _) => Less, + (Greater, _) => Greater, } } } @@ -156,7 +155,7 @@ macro_rules! forward_ref_binop { $imp::$method(*self, *other) } } - } + }; } /// Macro for deriving deref @@ -170,7 +169,7 @@ macro_rules! deref { &self.0 } } - } + }; } macro_rules! add { @@ -183,7 +182,7 @@ macro_rules! add { $construct(self.0 + rhs.0) } } - } + }; } macro_rules! sub { @@ -223,7 +222,7 @@ macro_rules! sub { $construct(self.0 - rhs.0) } } - } + }; } /// This exists because we can't implement Iterator on Range @@ -246,6 +245,7 @@ pub trait Contains { impl> Contains for Range { type Content = T; + fn contains_(&self, item: Self::Content) -> bool { (self.start <= item) && (item < self.end) } @@ -253,6 +253,7 @@ impl> Contains for Range { impl> Contains for RangeInclusive { type Content = T; + fn contains_(&self, item: Self::Content) -> bool { (self.start() <= &item) && (&item <= self.end()) } @@ -383,7 +384,7 @@ ops!(Linear, Linear); #[cfg(test)] mod tests { - use super::{Line, Column, Point}; + use super::{Column, Line, Point}; #[test] fn location_ordering() { diff --git a/src/input.rs b/src/input.rs index 51e4e71..8ce8f2c 100644 --- a/src/input.rs +++ b/src/input.rs @@ -20,27 +20,27 @@ //! determine what to do when a non-modifier key is pressed. use std::borrow::Cow; use std::mem; -use std::time::Instant; use std::ops::RangeInclusive; +use std::time::Instant; -use copypasta::{Clipboard, Load, Buffer as ClipboardBuffer}; -use unicode_width::UnicodeWidthStr; +use copypasta::{Buffer as ClipboardBuffer, Clipboard, Load}; use glutin::{ ElementState, KeyboardInput, ModifiersState, MouseButton, MouseCursor, MouseScrollDelta, TouchPhase, }; +use unicode_width::UnicodeWidthStr; +use crate::ansi::{ClearMode, Handler}; use crate::config::{self, Key}; -use crate::grid::Scroll; use crate::event::{ClickState, Mouse}; -use crate::index::{Line, Column, Side, Point, Linear}; -use crate::term::{Term, SizeInfo, Search}; +use crate::grid::Scroll; +use crate::index::{Column, Line, Linear, Point, Side}; +use crate::message_bar::{self, Message}; use crate::term::mode::TermMode; +use crate::term::{Search, SizeInfo, Term}; +use crate::url::Url; use crate::util::fmt::Red; use crate::util::start_daemon; -use crate::message_bar::{self, Message}; -use crate::ansi::{Handler, ClearMode}; -use crate::url::Url; pub const FONT_SIZE_STEP: f32 = 0.5; @@ -148,10 +148,10 @@ impl Binding { // 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.mods_match(mods, relaxed) + self.trigger == *input + && self.mode_matches(mode) + && self.not_mode_matches(mode) + && self.mods_match(mods, relaxed) } #[inline] @@ -267,8 +267,8 @@ impl Action { }, Action::Paste => { Clipboard::new() - .and_then(|clipboard| clipboard.load_primary() ) - .map(|contents| { self.paste(ctx, &contents) }) + .and_then(|clipboard| clipboard.load_primary()) + .map(|contents| self.paste(ctx, &contents)) .unwrap_or_else(|err| { error!("Error loading data from clipboard: {}", Red(err)); }); @@ -277,8 +277,8 @@ impl Action { // Only paste if mouse events are not captured by an application if !mouse_mode { Clipboard::new() - .and_then(|clipboard| clipboard.load_selection() ) - .map(|contents| { self.paste(ctx, &contents) }) + .and_then(|clipboard| clipboard.load_selection()) + .map(|contents| self.paste(ctx, &contents)) .unwrap_or_else(|err| { error!("Error loading data from clipboard: {}", Red(err)); }); @@ -303,13 +303,13 @@ impl Action { ctx.terminal_mut().exit(); }, Action::IncreaseFontSize => { - ctx.terminal_mut().change_font_size(FONT_SIZE_STEP); + ctx.terminal_mut().change_font_size(FONT_SIZE_STEP); }, Action::DecreaseFontSize => { - ctx.terminal_mut().change_font_size(-FONT_SIZE_STEP); - } + ctx.terminal_mut().change_font_size(-FONT_SIZE_STEP); + }, Action::ResetFontSize => { - ctx.terminal_mut().reset_font_size(); + ctx.terminal_mut().reset_font_size(); }, Action::ScrollPageUp => { ctx.scroll(Scroll::PageUp); @@ -339,7 +339,7 @@ impl Action { fn paste(&self, ctx: &mut A, contents: &str) { if ctx.terminal().mode().contains(TermMode::BRACKETED_PASTE) { ctx.write_to_pty(&b"\x1b[200~"[..]); - ctx.write_to_pty(contents.replace("\x1b","").into_bytes()); + ctx.write_to_pty(contents.replace("\x1b", "").into_bytes()); ctx.write_to_pty(&b"\x1b[201~"[..]); } else { // In non-bracketed (ie: normal) mode, terminal applications cannot distinguish @@ -348,7 +348,7 @@ impl Action { // pasting... since that's neither practical nor sensible (and probably an impossible // task to solve in a general way), we'll just replace line breaks (windows and unix // style) with a singe carriage return (\r, which is what the Enter key produces). - ctx.write_to_pty(contents.replace("\r\n","\r").replace("\n","\r").into_bytes()); + ctx.write_to_pty(contents.replace("\r\n", "\r").replace("\n", "\r").into_bytes()); } } } @@ -411,13 +411,7 @@ impl<'a, A: ActionContext + 'a> Processor<'a, A> { if self.ctx.mouse().left_button_state == ElementState::Pressed && (modifiers.shift || !self.ctx.terminal().mode().intersects(report_mode)) { - self.ctx.update_selection( - Point { - line: point.line, - col: point.col, - }, - cell_side, - ); + self.ctx.update_selection(Point { line: point.line, col: point.col }, cell_side); } else if self.ctx.terminal().mode().intersects(motion_mode) && size_info.contains_point(x, y, false) { @@ -443,7 +437,7 @@ impl<'a, A: ActionContext + 'a> Processor<'a, A> { && (!self.ctx.terminal().mode().intersects(mouse_mode) || modifiers.shift) && self.mouse_config.url.launcher.is_some() { - self.ctx.terminal().url_search(point.into()) + self.ctx.terminal().url_search(point.into()) } else { None }; @@ -582,14 +576,14 @@ impl<'a, A: ActionContext + 'a> Processor<'a, A> { self.ctx.mouse_mut().block_url_launcher = true; self.on_mouse_double_click(button, point); ClickState::DoubleClick - }, + } ClickState::DoubleClick if !button_changed && elapsed < self.mouse_config.triple_click.threshold => { self.ctx.mouse_mut().block_url_launcher = true; self.on_mouse_triple_click(button, point); ClickState::TripleClick - }, + } _ => { // Don't launch URLs if this click cleared the selection self.ctx.mouse_mut().block_url_launcher = !self.ctx.selection_is_empty(); @@ -617,7 +611,7 @@ impl<'a, A: ActionContext + 'a> Processor<'a, A> { } ClickState::Click - } + }, }; } @@ -690,7 +684,7 @@ impl<'a, A: ActionContext + 'a> Processor<'a, A> { }, _ => (), } - } + }, } } @@ -744,11 +738,7 @@ impl<'a, A: ActionContext + 'a> Processor<'a, A> { pub fn on_focus_change(&mut self, is_focused: bool) { if self.ctx.terminal().mode().contains(TermMode::FOCUS_IN_OUT) { - let chr = if is_focused { - "I" - } else { - "O" - }; + let chr = if is_focused { "I" } else { "O" }; let msg = format!("\x1b[{}", chr); self.ctx.write_to_pty(msg.into_bytes()); @@ -759,7 +749,7 @@ impl<'a, A: ActionContext + 'a> Processor<'a, A> { &mut self, state: ElementState, button: MouseButton, - modifiers: ModifiersState + modifiers: ModifiersState, ) { match button { MouseButton::Left => self.ctx.mouse_mut().left_button_state = state, @@ -849,16 +839,18 @@ impl<'a, A: ActionContext + 'a> Processor<'a, A> { &Key::Scancode(input.scancode), false, ), - _ => if let Some(key) = input.virtual_keycode { - let key = Key::from_glutin_input(key); - binding.is_triggered_by( - *self.ctx.terminal().mode(), - input.modifiers, - &key, + _ => { + if let Some(key) = input.virtual_keycode { + let key = Key::from_glutin_input(key); + binding.is_triggered_by( + *self.ctx.terminal().mode(), + input.modifiers, + &key, + false, + ) + } else { false - ) - } else { - false + } }, }; @@ -883,11 +875,12 @@ impl<'a, A: ActionContext + 'a> Processor<'a, A> { for binding in self.mouse_bindings { if binding.is_triggered_by(*self.ctx.terminal().mode(), mods, &button, true) { // binding was triggered; run the action - let mouse_mode = !mods.shift && self.ctx.terminal().mode().intersects( - TermMode::MOUSE_REPORT_CLICK - | TermMode::MOUSE_DRAG - | TermMode::MOUSE_MOTION - ); + let mouse_mode = !mods.shift + && self.ctx.terminal().mode().intersects( + TermMode::MOUSE_REPORT_CLICK + | TermMode::MOUSE_DRAG + | TermMode::MOUSE_MOTION, + ); binding.execute(&mut self.ctx, mouse_mode); has_binding = true; } @@ -898,10 +891,9 @@ impl<'a, A: ActionContext + 'a> Processor<'a, A> { /// Return the message bar's message if there is some at the specified point fn message_at_point(&mut self, point: Option) -> Option { - if let (Some(point), Some(message)) = ( - point, - self.ctx.terminal_mut().message_buffer_mut().message(), - ) { + if let (Some(point), Some(message)) = + (point, self.ctx.terminal_mut().message_buffer_mut().message()) + { let size = self.ctx.size_info(); if point.line.0 >= size.lines().saturating_sub(message.text(&size).len()) { return Some(message); @@ -924,7 +916,7 @@ impl<'a, A: ActionContext + 'a> Processor<'a, A> { } self.ctx.clear_selection(); - } + }, } } @@ -942,15 +934,15 @@ mod tests { use std::borrow::Cow; use std::time::Duration; - use glutin::{VirtualKeyCode, Event, WindowEvent, ElementState, MouseButton, ModifiersState}; + use glutin::{ElementState, Event, ModifiersState, MouseButton, VirtualKeyCode, WindowEvent}; - use crate::term::{SizeInfo, Term, TermMode}; - use crate::event::{Mouse, ClickState, WindowChanges}; - use crate::config::{self, Config, ClickHandler}; - use crate::index::{Point, Side}; - use crate::selection::Selection; + use crate::config::{self, ClickHandler, Config}; + use crate::event::{ClickState, Mouse, WindowChanges}; use crate::grid::Scroll; + use crate::index::{Point, Side}; use crate::message_bar::MessageBuffer; + use crate::selection::Selection; + use crate::term::{SizeInfo, Term, TermMode}; use super::{Action, Binding, Processor}; use copypasta::Buffer as ClipboardBuffer; @@ -976,13 +968,19 @@ mod tests { pub window_changes: &'a mut WindowChanges, } - impl <'a>super::ActionContext for ActionContext<'a> { + impl<'a> super::ActionContext for ActionContext<'a> { fn write_to_pty>>(&mut self, _val: B) {} + fn update_selection(&mut self, _point: Point, _side: Side) {} + fn simple_selection(&mut self, _point: Point, _side: Side) {} + fn copy_selection(&self, _buffer: ClipboardBuffer) {} + fn clear_selection(&mut self) {} + fn hide_window(&mut self) {} + fn spawn_new_instance(&mut self) {} fn terminal(&self) -> &Term { diff --git a/src/lib.rs b/src/lib.rs index 64d554c..92ccb5a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,8 +17,10 @@ #![cfg_attr(feature = "nightly", feature(core_intrinsics))] #![cfg_attr(all(test, feature = "bench"), feature(test))] -#[macro_use] extern crate log; -#[macro_use] extern crate serde_derive; +#[macro_use] +extern crate log; +#[macro_use] +extern crate serde_derive; #[cfg(target_os = "macos")] #[macro_use] @@ -37,6 +39,7 @@ pub mod index; pub mod input; pub mod locale; pub mod logging; +pub mod message_bar; pub mod meter; pub mod panic; pub mod renderer; @@ -44,10 +47,9 @@ pub mod selection; pub mod sync; pub mod term; pub mod tty; +mod url; pub mod util; pub mod window; -pub mod message_bar; -mod url; pub use crate::grid::Grid; pub use crate::term::Term; diff --git a/src/locale.rs b/src/locale.rs index 81904f7..40c915b 100644 --- a/src/locale.rs +++ b/src/locale.rs @@ -13,13 +13,13 @@ // limitations under the License. #![allow(clippy::let_unit_value)] #![cfg(target_os = "macos")] -use libc::{LC_CTYPE, setlocale}; -use std::ffi::{CString, CStr}; +use libc::{setlocale, LC_CTYPE}; +use std::env; +use std::ffi::{CStr, CString}; use std::os::raw::c_char; use std::ptr::null; use std::slice; use std::str; -use std::env; use objc::runtime::{Class, Object}; @@ -27,30 +27,32 @@ pub fn set_locale_environment() { let locale_id = unsafe { let locale_class = Class::get("NSLocale").unwrap(); let locale: *const Object = msg_send![locale_class, currentLocale]; - let _ : () = msg_send![locale_class, release]; + let _: () = msg_send![locale_class, release]; // `localeIdentifier` returns extra metadata with the locale (including currency and // collator) on newer versions of macOS. This is not a valid locale, so we use // `languageCode` and `countryCode`, if they're available (macOS 10.12+): // https://developer.apple.com/documentation/foundation/nslocale/1416263-localeidentifier?language=objc // https://developer.apple.com/documentation/foundation/nslocale/1643060-countrycode?language=objc // https://developer.apple.com/documentation/foundation/nslocale/1643026-languagecode?language=objc - let is_language_code_supported: bool = msg_send![locale, respondsToSelector:sel!(languageCode)]; - let is_country_code_supported: bool = msg_send![locale, respondsToSelector:sel!(countryCode)]; + let is_language_code_supported: bool = + msg_send![locale, respondsToSelector: sel!(languageCode)]; + let is_country_code_supported: bool = + msg_send![locale, respondsToSelector: sel!(countryCode)]; let locale_id = if is_language_code_supported && is_country_code_supported { let language_code: *const Object = msg_send![locale, languageCode]; let country_code: *const Object = msg_send![locale, countryCode]; let language_code_str = nsstring_as_str(language_code).to_owned(); - let _ : () = msg_send![language_code, release]; + let _: () = msg_send![language_code, release]; let country_code_str = nsstring_as_str(country_code).to_owned(); - let _ : () = msg_send![country_code, release]; + let _: () = msg_send![country_code, release]; format!("{}_{}.UTF-8", &language_code_str, &country_code_str) } else { let identifier: *const Object = msg_send![locale, localeIdentifier]; let identifier_str = nsstring_as_str(identifier).to_owned(); - let _ : () = msg_send![identifier, release]; + let _: () = msg_send![identifier, release]; identifier_str + ".UTF-8" }; - let _ : () = msg_send![locale, release]; + let _: () = msg_send![locale, release]; locale_id }; // check if locale_id is valid @@ -66,11 +68,7 @@ pub fn set_locale_environment() { }; // try setting `locale_id` let modified = setlocale(LC_CTYPE, locale_ptr); - let result = if modified.is_null() { - String::new() - } else { - locale_id - }; + let result = if modified.is_null() { String::new() } else { locale_id }; // restore original setting setlocale(LC_CTYPE, saved_original.as_ptr()); result diff --git a/src/logging.rs b/src/logging.rs index 0b1d25a..c6ddd8e 100644 --- a/src/logging.rs +++ b/src/logging.rs @@ -68,12 +68,7 @@ impl Logger { let logfile = Mutex::new(OnDemandLogFile::new()); let stdout = Mutex::new(LineWriter::new(io::stdout())); - Logger { - level, - logfile, - stdout, - message_tx, - } + Logger { level, logfile, stdout, message_tx } } fn file_path(&self) -> Option { @@ -100,10 +95,7 @@ impl log::Log for Logger { now, record.level(), record.file().unwrap_or("?"), - record - .line() - .map(|l| l.to_string()) - .unwrap_or_else(|| "?".into()), + record.line().map(|l| l.to_string()).unwrap_or_else(|| "?".into()), record.args() ) } else { @@ -161,11 +153,7 @@ impl OnDemandLogFile { // Set log path as an environment variable env::set_var(ALACRITTY_LOG_ENV, path.as_os_str()); - OnDemandLogFile { - path, - file: None, - created: Arc::new(AtomicBool::new(false)), - } + OnDemandLogFile { path, file: None, created: Arc::new(AtomicBool::new(false)) } } fn file(&mut self) -> Result<&mut LineWriter, io::Error> { @@ -176,21 +164,18 @@ impl OnDemandLogFile { // Create the file if it doesn't exist yet if self.file.is_none() { - let file = OpenOptions::new() - .append(true) - .create(true) - .open(&self.path); + let file = OpenOptions::new().append(true).create(true).open(&self.path); match file { Ok(file) => { self.file = Some(io::LineWriter::new(file)); self.created.store(true, Ordering::Relaxed); let _ = writeln!(io::stdout(), "Created log file at {:?}", self.path); - } + }, Err(e) => { let _ = writeln!(io::stdout(), "Unable to create log file: {}", e); return Err(e); - } + }, } } diff --git a/src/main.rs b/src/main.rs index d5142db..d7e335e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,7 +16,6 @@ #![deny(clippy::all, clippy::if_not_else, clippy::enum_glob_use, clippy::wrong_pub_self_convention)] #![cfg_attr(feature = "nightly", feature(core_intrinsics))] #![cfg_attr(all(test, feature = "bench"), feature(test))] - // With the default subsystem, 'console', windows creates an additional console // window for the program. // This is silently ignored on non-windows systems. @@ -29,12 +28,12 @@ use dirs; #[cfg(windows)] use winapi::um::wincon::{AttachConsole, FreeConsole, ATTACH_PARENT_PROCESS}; -use log::{info, error}; +use log::{error, info}; use std::error::Error; -use std::sync::Arc; -use std::io::{self, Write}; use std::fs; +use std::io::{self, Write}; +use std::sync::Arc; #[cfg(target_os = "macos")] use std::env; @@ -42,19 +41,19 @@ use std::env; #[cfg(not(windows))] use std::os::unix::io::AsRawFd; -#[cfg(target_os = "macos")] -use alacritty::locale; -use alacritty::{cli, event, die}; use alacritty::config::{self, Config, Monitor}; use alacritty::display::Display; use alacritty::event_loop::{self, EventLoop, Msg}; +#[cfg(target_os = "macos")] +use alacritty::locale; use alacritty::logging; +use alacritty::message_bar::MessageBuffer; use alacritty::panic; use alacritty::sync::FairMutex; use alacritty::term::Term; use alacritty::tty; use alacritty::util::fmt::Red; -use alacritty::message_bar::MessageBuffer; +use alacritty::{cli, die, event}; fn main() { panic::attach_handler(); @@ -63,7 +62,9 @@ fn main() { // to the console of the parent process, so we do it explicitly. This fails // silently if the parent has no console. #[cfg(windows)] - unsafe { AttachConsole(ATTACH_PARENT_PROCESS); } + unsafe { + AttachConsole(ATTACH_PARENT_PROCESS); + } // Load command line options let options = cli::Options::load(); @@ -77,7 +78,8 @@ fn main() { // Load configuration file // If the file is a command line argument, we won't write a generated default file - let config_path = options.config_path() + let config_path = options + .config_path() .or_else(Config::installed_config) .or_else(|| Config::write_defaults().ok()) .map(|path| path.to_path_buf()); @@ -133,11 +135,7 @@ fn run( // The display manages a window and can draw the terminal let mut display = Display::new(&config, options)?; - info!( - "PTY Dimensions: {:?} x {:?}", - display.size().lines(), - display.size().cols() - ); + info!("PTY Dimensions: {:?} x {:?}", display.size().lines(), display.size().cols()); // Create the terminal // @@ -173,12 +171,8 @@ fn run( // renderer and input processing. Note that access to the terminal state is // synchronized since the I/O loop updates the state, and the display // consumes it periodically. - let event_loop = EventLoop::new( - Arc::clone(&terminal), - display.notifier(), - pty, - options.ref_test, - ); + let event_loop = + EventLoop::new(Arc::clone(&terminal), display.notifier(), pty, options.ref_test); // The event loop channel allows write requests from the event processor // to be sent to the loop and ultimately written to the pty. @@ -259,16 +253,16 @@ fn run( } } - loop_tx - .send(Msg::Shutdown) - .expect("Error sending shutdown to event loop"); + loop_tx.send(Msg::Shutdown).expect("Error sending shutdown to event loop"); // FIXME patch notify library to have a shutdown method // config_reloader.join().ok(); // Without explicitly detaching the console cmd won't redraw it's prompt #[cfg(windows)] - unsafe { FreeConsole(); } + unsafe { + FreeConsole(); + } info!("Goodbye"); diff --git a/src/message_bar.rs b/src/message_bar.rs index d7f27e7..8883dcb 100644 --- a/src/message_bar.rs +++ b/src/message_bar.rs @@ -33,11 +33,7 @@ pub struct Message { impl Message { /// Create a new message pub fn new(text: String, color: Rgb) -> Message { - Message { - text, - color, - topic: None, - } + Message { text, color, topic: None } } /// Formatted message text lines @@ -135,11 +131,7 @@ impl MessageBuffer { /// Create new message buffer pub fn new() -> MessageBuffer { let (tx, messages) = crossbeam_channel::unbounded(); - MessageBuffer { - current: None, - messages, - tx, - } + MessageBuffer { current: None, messages, tx } } /// Check if there are any messages queued @@ -215,10 +207,7 @@ mod test { fn appends_close_button() { let input = "a"; let mut message_buffer = MessageBuffer::new(); - message_buffer - .tx() - .send(Message::new(input.into(), color::RED)) - .unwrap(); + message_buffer.tx().send(Message::new(input.into(), color::RED)).unwrap(); let size = SizeInfo { width: 7., height: 10., @@ -238,10 +227,7 @@ mod test { fn multiline_close_button_first_line() { let input = "fo\nbar"; let mut message_buffer = MessageBuffer::new(); - message_buffer - .tx() - .send(Message::new(input.into(), color::RED)) - .unwrap(); + message_buffer.tx().send(Message::new(input.into(), color::RED)).unwrap(); let size = SizeInfo { width: 6., height: 10., @@ -261,10 +247,7 @@ mod test { fn splits_on_newline() { let input = "a\nb"; let mut message_buffer = MessageBuffer::new(); - message_buffer - .tx() - .send(Message::new(input.into(), color::RED)) - .unwrap(); + message_buffer.tx().send(Message::new(input.into(), color::RED)).unwrap(); let size = SizeInfo { width: 6., height: 10., @@ -284,10 +267,7 @@ mod test { fn splits_on_length() { let input = "foobar1"; let mut message_buffer = MessageBuffer::new(); - message_buffer - .tx() - .send(Message::new(input.into(), color::RED)) - .unwrap(); + message_buffer.tx().send(Message::new(input.into(), color::RED)).unwrap(); let size = SizeInfo { width: 6., height: 10., @@ -307,10 +287,7 @@ mod test { fn empty_with_shortterm() { let input = "foobar"; let mut message_buffer = MessageBuffer::new(); - message_buffer - .tx() - .send(Message::new(input.into(), color::RED)) - .unwrap(); + message_buffer.tx().send(Message::new(input.into(), color::RED)).unwrap(); let size = SizeInfo { width: 6., height: 0., @@ -330,10 +307,7 @@ mod test { fn truncates_long_messages() { let input = "hahahahahahahahahahaha truncate this because it's too long for the term"; let mut message_buffer = MessageBuffer::new(); - message_buffer - .tx() - .send(Message::new(input.into(), color::RED)) - .unwrap(); + message_buffer.tx().send(Message::new(input.into(), color::RED)).unwrap(); let size = SizeInfo { width: 22., height: (MIN_FREE_LINES + 2) as f32, @@ -346,23 +320,17 @@ mod test { let lines = message_buffer.message().unwrap().text(&size); - assert_eq!( - lines, - vec![ - String::from("hahahahahahahahaha [X]"), - String::from("[MESSAGE TRUNCATED] ") - ] - ); + assert_eq!(lines, vec![ + String::from("hahahahahahahahaha [X]"), + String::from("[MESSAGE TRUNCATED] ") + ]); } #[test] fn hide_button_when_too_narrow() { let input = "ha"; let mut message_buffer = MessageBuffer::new(); - message_buffer - .tx() - .send(Message::new(input.into(), color::RED)) - .unwrap(); + message_buffer.tx().send(Message::new(input.into(), color::RED)).unwrap(); let size = SizeInfo { width: 2., height: 10., @@ -382,10 +350,7 @@ mod test { fn hide_truncated_when_too_narrow() { let input = "hahahahahahahahaha"; let mut message_buffer = MessageBuffer::new(); - message_buffer - .tx() - .send(Message::new(input.into(), color::RED)) - .unwrap(); + message_buffer.tx().send(Message::new(input.into(), color::RED)).unwrap(); let size = SizeInfo { width: 2., height: (MIN_FREE_LINES + 2) as f32, @@ -405,10 +370,7 @@ mod test { fn add_newline_for_button() { let input = "test"; let mut message_buffer = MessageBuffer::new(); - message_buffer - .tx() - .send(Message::new(input.into(), color::RED)) - .unwrap(); + message_buffer.tx().send(Message::new(input.into(), color::RED)).unwrap(); let size = SizeInfo { width: 5., height: 10., @@ -466,10 +428,7 @@ mod test { fn wrap_on_words() { let input = "a\nbc defg"; let mut message_buffer = MessageBuffer::new(); - message_buffer - .tx() - .send(Message::new(input.into(), color::RED)) - .unwrap(); + message_buffer.tx().send(Message::new(input.into(), color::RED)).unwrap(); let size = SizeInfo { width: 5., height: 10., @@ -482,14 +441,11 @@ mod test { let lines = message_buffer.message().unwrap().text(&size); - assert_eq!( - lines, - vec![ - String::from("a [X]"), - String::from("bc "), - String::from("defg ") - ] - ); + assert_eq!(lines, vec![ + String::from("a [X]"), + String::from("bc "), + String::from("defg ") + ]); } #[test] diff --git a/src/meter.rs b/src/meter.rs index 32650e4..81da444 100644 --- a/src/meter.rs +++ b/src/meter.rs @@ -31,7 +31,7 @@ //! // the average won't mean much until it's filled up at least once. //! println!("Average time: {}", meter.average()); -use std::time::{Instant, Duration}; +use std::time::{Duration, Instant}; const NUM_SAMPLES: usize = 10; @@ -61,10 +61,7 @@ pub struct Sampler<'a> { impl<'a> Sampler<'a> { fn new(meter: &'a mut Meter) -> Sampler<'a> { - Sampler { - meter, - created_at: Instant::now(), - } + Sampler { meter, created_at: Instant::now() } } #[inline] diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index 6258ba6..b7b4f21 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -22,17 +22,17 @@ use std::sync::mpsc; use std::time::Duration; use fnv::FnvHasher; -use glutin::dpi::PhysicalSize; use font::{self, FontDesc, FontKey, GlyphKey, Rasterize, RasterizedGlyph, Rasterizer}; +use glutin::dpi::PhysicalSize; use notify::{watcher, DebouncedEvent, RecursiveMode, Watcher}; -use crate::gl::types::*; -use crate::gl; -use crate::index::{Column, Line}; -use crate::term::color::Rgb; use crate::config::{self, Config, Delta}; -use crate::term::{self, cell, RenderableCell}; +use crate::gl; +use crate::gl::types::*; +use crate::index::{Column, Line}; use crate::renderer::rects::{Rect, Rects}; +use crate::term::color::Rgb; +use crate::term::{self, cell, RenderableCell}; pub mod rects; @@ -91,7 +91,7 @@ impl ::std::fmt::Display for Error { match *self { Error::ShaderCreation(ref err) => { write!(f, "There was an error initializing the shaders: {}", err) - } + }, } } } @@ -214,11 +214,7 @@ impl GlyphCache { fn load_glyphs_for_font(&mut self, font: FontKey, loader: &mut L) { let size = self.font_size; for i in 32u8..=128u8 { - self.get(GlyphKey { - font_key: font, - c: i as char, - size, - }, loader); + self.get(GlyphKey { font_key: font, c: i as char, size }, loader); } } @@ -230,7 +226,8 @@ impl GlyphCache { let size = font.size(); // Load regular font - let regular_desc = Self::make_desc(&font.normal(), font::Slant::Normal, font::Weight::Normal); + let regular_desc = + Self::make_desc(&font.normal(), font::Slant::Normal, font::Weight::Normal); let regular = rasterizer.load_font(®ular_desc, size)?; @@ -239,9 +236,7 @@ impl GlyphCache { if desc == regular_desc { regular } else { - rasterizer - .load_font(&desc, size) - .unwrap_or_else(|_| regular) + rasterizer.load_font(&desc, size).unwrap_or_else(|_| regular) } }; @@ -251,7 +246,8 @@ impl GlyphCache { let bold = load_or_regular(bold_desc); // Load italic font - let italic_desc = Self::make_desc(&font.italic(), font::Slant::Italic, font::Weight::Normal); + let italic_desc = + Self::make_desc(&font.italic(), font::Slant::Italic, font::Weight::Normal); let italic = load_or_regular(italic_desc); @@ -278,30 +274,30 @@ impl GlyphCache { } pub fn get<'a, L>(&'a mut self, glyph_key: GlyphKey, loader: &mut L) -> &'a Glyph - where L: LoadGlyph + where + L: LoadGlyph, { let glyph_offset = self.glyph_offset; let rasterizer = &mut self.rasterizer; let metrics = &self.metrics; - self.cache - .entry(glyph_key) - .or_insert_with(|| { - let mut rasterized = rasterizer.get_glyph(glyph_key) - .unwrap_or_else(|_| Default::default()); + self.cache.entry(glyph_key).or_insert_with(|| { + let mut rasterized = + rasterizer.get_glyph(glyph_key).unwrap_or_else(|_| Default::default()); - rasterized.left += i32::from(glyph_offset.x); - rasterized.top += i32::from(glyph_offset.y); - rasterized.top -= metrics.descent as i32; + rasterized.left += i32::from(glyph_offset.x); + rasterized.top += i32::from(glyph_offset.y); + rasterized.top -= metrics.descent as i32; - loader.load_glyph(&rasterized) + loader.load_glyph(&rasterized) }) } + pub fn update_font_size( &mut self, font: &config::Font, size: font::Size, dpr: f64, - loader: &mut L + loader: &mut L, ) -> Result<(), font::Error> { // Clear currently cached data in both GL and the registry loader.clear(); @@ -410,10 +406,7 @@ pub struct Batch { impl Batch { #[inline] pub fn new() -> Batch { - Batch { - tex: 0, - instances: Vec::with_capacity(BATCH_MAX), - } + Batch { tex: 0, instances: Vec::with_capacity(BATCH_MAX) } } pub fn add_item(&mut self, cell: &RenderableCell, glyph: &Glyph) { @@ -592,16 +585,13 @@ impl QuadRenderer { gl::GenBuffers(1, &mut rect_vbo); gl::GenBuffers(1, &mut rect_ebo); gl::BindVertexArray(rect_vao); - let indices: [i32; 6] = [ - 0, 1, 3, - 1, 2, 3, - ]; + let indices: [i32; 6] = [0, 1, 3, 1, 2, 3]; gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, rect_ebo); gl::BufferData( gl::ELEMENT_ARRAY_BUFFER, (size_of::() * indices.len()) as _, indices.as_ptr() as *const _, - gl::STATIC_DRAW + gl::STATIC_DRAW, ); // Cleanup @@ -629,13 +619,13 @@ impl QuadRenderer { let event = rx.recv().expect("watcher event"); match event { - DebouncedEvent::Rename(_, _) => continue, + DebouncedEvent::Rename(..) => continue, DebouncedEvent::Create(_) | DebouncedEvent::Write(_) | DebouncedEvent::Chmod(_) => { msg_tx.send(Msg::ShaderReload).expect("msg send ok"); - } - _ => {} + }, + _ => {}, } } }); @@ -686,7 +676,14 @@ impl QuadRenderer { gl::BindBuffer(gl::ARRAY_BUFFER, self.rect_vbo); // Position - gl::VertexAttribPointer(0, 2, gl::FLOAT, gl::FALSE, (size_of::() * 2) as _, ptr::null()); + gl::VertexAttribPointer( + 0, + 2, + gl::FLOAT, + gl::FALSE, + (size_of::() * 2) as _, + ptr::null(), + ); gl::EnableVertexAttribArray(0); } @@ -720,12 +717,7 @@ impl QuadRenderer { } } - pub fn with_api( - &mut self, - config: &Config, - props: &term::SizeInfo, - func: F, - ) -> T + pub fn with_api(&mut self, config: &Config, props: &term::SizeInfo, func: F) -> T where F: FnOnce(RenderApi<'_>) -> T, { @@ -788,11 +780,11 @@ impl QuadRenderer { (Ok(program), Ok(rect_program)) => { info!("... successfully reloaded shaders"); (program, rect_program) - } + }, (Err(err), _) | (_, Err(err)) => { error!("{}", err); return; - } + }, }; self.active_tex = 0; @@ -842,19 +834,14 @@ impl QuadRenderer { unsafe { // Setup vertices - let vertices: [f32; 8] = [ - x + width, y , - x + width, y - height, - x , y - height, - x , y , - ]; + let vertices: [f32; 8] = [x + width, y, x + width, y - height, x, y - height, x, y]; // Load vertex data into array buffer gl::BufferData( gl::ARRAY_BUFFER, (size_of::() * vertices.len()) as _, vertices.as_ptr() as *const _, - gl::STATIC_DRAW + gl::STATIC_DRAW, ); // Color @@ -927,7 +914,7 @@ impl<'a> RenderApi<'a> { string: &str, line: Line, glyph_cache: &mut GlyphCache, - color: Option + color: Option, ) { let bg_alpha = color.map(|_| 1.0).unwrap_or(0.0); let col = Column(0); @@ -943,7 +930,7 @@ impl<'a> RenderApi<'a> { chars[0] = c; chars }, - bg: color.unwrap_or(Rgb { r: 0, g: 0, b: 0}), + bg: color.unwrap_or(Rgb { r: 0, g: 0, b: 0 }), fg: Rgb { r: 0, g: 0, b: 0 }, flags: cell::Flags::empty(), bg_alpha, @@ -993,11 +980,7 @@ impl<'a> RenderApi<'a> { chars[0] = ' '; } - let mut glyph_key = GlyphKey { - font_key, - size: glyph_cache.font_size, - c: chars[0], - }; + let mut glyph_key = GlyphKey { font_key, size: glyph_cache.font_size, c: chars[0] }; // Add cell to batch let glyph = glyph_cache.get(glyph_key, self); @@ -1028,7 +1011,7 @@ fn load_glyph( active_tex: &mut GLuint, atlas: &mut Vec, current_atlas: &mut usize, - rasterized: &RasterizedGlyph + rasterized: &RasterizedGlyph, ) -> Glyph { // At least one atlas is guaranteed to be in the `self.atlas` list; thus // the unwrap. @@ -1042,20 +1025,18 @@ fn load_glyph( atlas.push(new); } load_glyph(active_tex, atlas, current_atlas, rasterized) - } - Err(AtlasInsertError::GlyphTooLarge) => { - Glyph { - tex_id: atlas[*current_atlas].id, - top: 0.0, - left: 0.0, - width: 0.0, - height: 0.0, - uv_bot: 0.0, - uv_left: 0.0, - uv_width: 0.0, - uv_height: 0.0, - } - } + }, + Err(AtlasInsertError::GlyphTooLarge) => Glyph { + tex_id: atlas[*current_atlas].id, + top: 0.0, + left: 0.0, + width: 0.0, + height: 0.0, + uv_bot: 0.0, + uv_left: 0.0, + uv_width: 0.0, + uv_height: 0.0, + }, } } @@ -1113,7 +1094,9 @@ impl TextShaderProgram { } macro_rules! cptr { - ($thing:expr) => { $thing.as_ptr() as *const _ } + ($thing:expr) => { + $thing.as_ptr() as *const _ + }; } macro_rules! assert_uniform_valid { @@ -1146,16 +1129,16 @@ impl TextShaderProgram { shader.update_projection(size.width as f32, size.height as f32, 0., 0.); - unsafe { gl::UseProgram(0); } + unsafe { + gl::UseProgram(0); + } Ok(shader) } fn update_projection(&self, width: f32, height: f32, padding_x: f32, padding_y: f32) { // Bounds check - if (width as u32) < (2 * padding_x as u32) || - (height as u32) < (2 * padding_y as u32) - { + if (width as u32) < (2 * padding_x as u32) || (height as u32) < (2 * padding_y as u32) { return; } @@ -1204,16 +1187,8 @@ impl RectShaderProgram { } else { (Some(RECT_SHADER_V), Some(RECT_SHADER_F)) }; - let vertex_shader = create_shader( - RECT_SHADER_V_PATH, - gl::VERTEX_SHADER, - vertex_src - )?; - let fragment_shader = create_shader( - RECT_SHADER_F_PATH, - gl::FRAGMENT_SHADER, - fragment_src - )?; + let vertex_shader = create_shader(RECT_SHADER_V_PATH, gl::VERTEX_SHADER, vertex_src)?; + let fragment_shader = create_shader(RECT_SHADER_F_PATH, gl::FRAGMENT_SHADER, fragment_src)?; let program = create_program(vertex_shader, fragment_shader)?; unsafe { @@ -1223,14 +1198,9 @@ impl RectShaderProgram { } // get uniform locations - let u_color = unsafe { - gl::GetUniformLocation(program, b"color\0".as_ptr() as *const _) - }; + let u_color = unsafe { gl::GetUniformLocation(program, b"color\0".as_ptr() as *const _) }; - let shader = RectShaderProgram { - id: program, - u_color, - }; + let shader = RectShaderProgram { id: program, u_color }; unsafe { gl::UseProgram(0) } @@ -1276,9 +1246,11 @@ fn create_program(vertex: GLuint, fragment: GLuint) -> Result) - -> Result -{ +fn create_shader( + path: &str, + kind: GLenum, + source: Option<&'static str>, +) -> Result { let from_disk; let source = if let Some(src) = source { src @@ -1308,7 +1280,9 @@ fn create_shader(path: &str, kind: GLenum, source: Option<&'static str>) let log = get_shader_info_log(shader); // Cleanup - unsafe { gl::DeleteShader(shader); } + unsafe { + gl::DeleteShader(shader); + } Err(ShaderCreationError::Compile(PathBuf::from(path), log)) } @@ -1325,12 +1299,7 @@ fn get_program_info_log(program: GLuint) -> String { let mut actual_length: GLint = 0; let mut buf: Vec = Vec::with_capacity(max_length as usize); unsafe { - gl::GetProgramInfoLog( - program, - max_length, - &mut actual_length, - buf.as_mut_ptr() as *mut _, - ); + gl::GetProgramInfoLog(program, max_length, &mut actual_length, buf.as_mut_ptr() as *mut _); } // Build a string @@ -1353,12 +1322,7 @@ fn get_shader_info_log(shader: GLuint) -> String { let mut actual_length: GLint = 0; let mut buf: Vec = Vec::with_capacity(max_length as usize); unsafe { - gl::GetShaderInfoLog( - shader, - max_length, - &mut actual_length, - buf.as_mut_ptr() as *mut _, - ); + gl::GetShaderInfoLog(shader, max_length, &mut actual_length, buf.as_mut_ptr() as *mut _); } // Build a string @@ -1410,15 +1374,11 @@ impl ::std::error::Error for ShaderCreationError { impl ::std::fmt::Display for ShaderCreationError { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { match *self { - ShaderCreationError::Io(ref err) => { - write!(f, "Couldn't read shader: {}", err) - }, + ShaderCreationError::Io(ref err) => write!(f, "Couldn't read shader: {}", err), ShaderCreationError::Compile(ref path, ref log) => { write!(f, "Failed compiling shader at {}: {}", path.display(), log) }, - ShaderCreationError::Link(ref log) => { - write!(f, "Failed linking shader: {}", log) - }, + ShaderCreationError::Link(ref log) => write!(f, "Failed linking shader: {}", log), } } } @@ -1509,14 +1469,7 @@ impl Atlas { gl::BindTexture(gl::TEXTURE_2D, 0); } - Atlas { - id, - width: size, - height: size, - row_extent: 0, - row_baseline: 0, - row_tallest: 0, - } + Atlas { id, width: size, height: size, row_extent: 0, row_baseline: 0, row_tallest: 0 } } pub fn clear(&mut self) { @@ -1529,7 +1482,7 @@ impl Atlas { pub fn insert( &mut self, glyph: &RasterizedGlyph, - active_tex: &mut u32 + active_tex: &mut u32, ) -> Result { if glyph.width > self.width || glyph.height > self.height { return Err(AtlasInsertError::GlyphTooLarge); diff --git a/src/renderer/rects.rs b/src/renderer/rects.rs index e066c36..e6a4563 100644 --- a/src/renderer/rects.rs +++ b/src/renderer/rects.rs @@ -14,8 +14,8 @@ use std::collections::HashMap; use crate::term::cell::Flags; -use crate::term::{RenderableCell, SizeInfo}; use crate::term::color::Rgb; +use crate::term::{RenderableCell, SizeInfo}; use font::Metrics; #[derive(Debug, Copy, Clone)] @@ -47,13 +47,7 @@ impl<'a> Rects<'a> { last_starts.insert(Flags::UNDERLINE, None); last_starts.insert(Flags::STRIKEOUT, None); - Self { - inner: Vec::new(), - last_cell: None, - last_starts, - metrics, - size, - } + Self { inner: Vec::new(), last_cell: None, last_starts, metrics, size } } /// Convert the stored rects to rectangles for the renderer. @@ -61,15 +55,13 @@ impl<'a> Rects<'a> { // If there's still a line pending, draw it until the last cell for (flag, start_cell) in self.last_starts.iter_mut() { if let Some(start) = start_cell { - self.inner.push( - create_rect( - &start, - &self.last_cell.unwrap(), - *flag, - &self.metrics, - &self.size, - ) - ); + self.inner.push(create_rect( + &start, + &self.last_cell.unwrap(), + *flag, + &self.metrics, + &self.size, + )); } } @@ -108,12 +100,14 @@ impl<'a> Rects<'a> { } else { None } - } + }, // Check for new start of line - None => if cell.flags.contains(flag) { - Some(*cell) - } else { - None + None => { + if cell.flags.contains(flag) { + Some(*cell) + } else { + None + } }, }; } @@ -158,12 +152,8 @@ fn create_rect( y = max_y; } - let rect = Rect::new( - start_x + size.padding_x, - y.round() + size.padding_y, - width, - height.round(), - ); + let rect = + Rect::new(start_x + size.padding_x, y.round() + size.padding_y, width, height.round()); (rect, start.fg) } diff --git a/src/selection.rs b/src/selection.rs index 8009b80..d200958 100644 --- a/src/selection.rs +++ b/src/selection.rs @@ -18,10 +18,10 @@ //! finalized when the button is released. The selection should be cleared //! when text is added/removed/scrolled on the screen. The selection should //! also be cleared if the user clicks off of the selection. -use std::cmp::{min, max}; +use std::cmp::{max, min}; use std::ops::Range; -use crate::index::{Point, Column, Side}; +use crate::index::{Column, Point, Side}; use crate::term::Search; /// Describes a region of a 2-dimensional area @@ -55,8 +55,8 @@ pub enum Selection { /// The line under the initial point. This is always selected regardless /// of which way the cursor is moved. - initial_line: isize - } + initial_line: isize, + }, } /// A Point and side within that point. @@ -83,8 +83,8 @@ impl Selection { Selection::Simple { region: Range { start: Anchor::new(location.into(), side), - end: Anchor::new(location.into(), side) - } + end: Anchor::new(location.into(), side), + }, } } @@ -102,25 +102,17 @@ impl Selection { region.start.line += offset; region.end.line += offset; *initial_line += offset; - } + }, } } pub fn semantic(point: Point) -> Selection { - Selection::Semantic { - region: Range { - start: point.into(), - end: point.into(), - } - } + Selection::Semantic { region: Range { start: point.into(), end: point.into() } } } pub fn lines(point: Point) -> Selection { Selection::Lines { - region: Range { - start: point.into(), - end: point.into(), - }, + region: Range { start: point.into(), end: point.into() }, initial_line: point.line as isize, } } @@ -131,9 +123,7 @@ impl Selection { Selection::Simple { ref mut region } => { region.end = Anchor::new(location.into(), side); }, - Selection::Semantic { ref mut region } | - Selection::Lines { ref mut region, .. } => - { + Selection::Semantic { ref mut region } | Selection::Lines { ref mut region, .. } => { region.end = location.into(); }, } @@ -144,36 +134,28 @@ impl Selection { G: Search + Dimensions, { match *self { - Selection::Simple { ref region } => { - Selection::span_simple(grid, region, alt_screen) - }, + Selection::Simple { ref region } => Selection::span_simple(grid, region, alt_screen), Selection::Semantic { ref region } => { Selection::span_semantic(grid, region, alt_screen) }, Selection::Lines { ref region, initial_line } => { Selection::span_lines(grid, region, initial_line, alt_screen) - } + }, } } - pub fn is_empty(&self) -> bool - { + pub fn is_empty(&self) -> bool { match *self { Selection::Simple { ref region } => { region.start == region.end && region.start.side == region.end.side }, - Selection::Semantic { .. } | Selection::Lines { .. } => { - false - }, + Selection::Semantic { .. } | Selection::Lines { .. } => false, } } - fn span_semantic( - grid: &G, - region: &Range>, - alt_screen: bool, - ) -> Option - where G: Search + Dimensions + fn span_semantic(grid: &G, region: &Range>, alt_screen: bool) -> Option + where + G: Search + Dimensions, { let cols = grid.dimensions().col; let lines = grid.dimensions().line.0 as isize; @@ -199,12 +181,7 @@ impl Selection { ::std::mem::swap(&mut start, &mut end); } - Some(Span { - cols, - front: start, - tail: end, - ty: SpanType::Inclusive, - }) + Some(Span { cols, front: start, tail: end, ty: SpanType::Inclusive }) } fn span_lines( @@ -214,21 +191,15 @@ impl Selection { alt_screen: bool, ) -> Option where - G: Dimensions + G: Dimensions, { let cols = grid.dimensions().col; let lines = grid.dimensions().line.0 as isize; // First, create start and end points based on initial line and the grid // dimensions. - let mut start = Point { - col: cols - 1, - line: initial_line - }; - let mut end = Point { - col: Column(0), - line: initial_line - }; + let mut start = Point { col: cols - 1, line: initial_line }; + let mut end = Point { col: Column(0), line: initial_line }; // Now, expand lines based on where cursor started and ended. if region.start.line < region.end.line { @@ -245,17 +216,12 @@ impl Selection { Selection::alt_screen_clamp(&mut start, &mut end, lines, cols)?; } - Some(Span { - cols, - front: start.into(), - tail: end.into(), - ty: SpanType::Inclusive - }) + Some(Span { cols, front: start.into(), tail: end.into(), ty: SpanType::Inclusive }) } fn span_simple(grid: &G, region: &Range, alt_screen: bool) -> Option where - G: Dimensions + G: Dimensions, { let start = region.start.point; let start_side = region.start.side; @@ -276,7 +242,9 @@ impl Selection { // No selection for single cell with identical sides or two cell with right+left sides if (front == tail && front_side == tail_side) - || (tail_side == Side::Right && front_side == Side::Left && front.line == tail.line + || (tail_side == Side::Right + && front_side == Side::Left + && front.line == tail.line && front.col == tail.col + 1) { return None; @@ -303,12 +271,7 @@ impl Selection { } // Return the selection with all cells inclusive - Some(Span { - cols, - front: front.into(), - tail: tail.into(), - ty: SpanType::Inclusive, - }) + Some(Span { cols, front: front.into(), tail: tail.into(), ty: SpanType::Inclusive }) } // Clamp selection in the alternate screen to the visible region @@ -387,7 +350,7 @@ impl Span { (Span::wrap_start(self.front, self.cols), Span::wrap_end(self.tail, self.cols)) }, SpanType::ExcludeFront => (Span::wrap_start(self.front, self.cols), self.tail), - SpanType::ExcludeTail => (self.front, Span::wrap_end(self.tail, self.cols)) + SpanType::ExcludeTail => (self.front, Span::wrap_end(self.tail, self.cols)), }; Locations { start, end } @@ -395,10 +358,7 @@ impl Span { fn wrap_start(mut start: Point, cols: Column) -> Point { if start.col == cols - 1 { - Point { - line: start.line + 1, - col: Column(0), - } + Point { line: start.line + 1, col: Column(0) } } else { start.col += 1; start @@ -407,15 +367,9 @@ impl Span { fn wrap_end(end: Point, cols: Column) -> Point { if end.col == Column(0) && end.line != 0 { - Point { - line: end.line - 1, - col: cols - } + Point { line: end.line - 1, col: cols } } else { - Point { - line: end.line, - col: end.col - 1 - } + Point { line: end.line, col: end.col - 1 } } } } @@ -431,8 +385,8 @@ impl Span { /// look like [ B] and [E ]. #[cfg(test)] mod test { - use crate::index::{Line, Column, Side, Point}; use super::{Selection, Span, SpanType}; + use crate::index::{Column, Line, Point, Side}; use crate::url::Url; struct Dimensions(Point); @@ -444,17 +398,22 @@ mod test { impl Dimensions { pub fn new(line: usize, col: usize) -> Self { - Dimensions(Point { - line: Line(line), - col: Column(col) - }) + Dimensions(Point { line: Line(line), col: Column(col) }) } } impl super::Search for Dimensions { - fn semantic_search_left(&self, point: Point) -> Point { point } - fn semantic_search_right(&self, point: Point) -> Point { point } - fn url_search(&self, _: Point) -> Option { None } + fn semantic_search_left(&self, point: Point) -> Point { + point + } + + fn semantic_search_right(&self, point: Point) -> Point { + point + } + + fn url_search(&self, _: Point) -> Option { + None + } } /// Test case of single cell selection diff --git a/src/sync.rs b/src/sync.rs index 06d6cea..0fcd086 100644 --- a/src/sync.rs +++ b/src/sync.rs @@ -31,10 +31,7 @@ pub struct FairMutex { impl FairMutex { /// Create a new fair mutex pub fn new(data: T) -> FairMutex { - FairMutex { - data: Mutex::new(data), - next: Mutex::new(()), - } + FairMutex { data: Mutex::new(data), next: Mutex::new(()) } } /// Lock the mutex diff --git a/src/term/cell.rs b/src/term/cell.rs index 88f9d7a..4d2f4c1 100644 --- a/src/term/cell.rs +++ b/src/term/cell.rs @@ -13,7 +13,7 @@ // limitations under the License. use bitflags::bitflags; -use crate::ansi::{NamedColor, Color}; +use crate::ansi::{Color, NamedColor}; use crate::grid::{self, GridCell}; use crate::index::Column; @@ -47,19 +47,14 @@ pub struct Cell { pub fg: Color, pub bg: Color, pub flags: Flags, - #[serde(default="default_extra")] + #[serde(default = "default_extra")] pub extra: [char; MAX_ZEROWIDTH_CHARS], } impl Default for Cell { fn default() -> Cell { - Cell::new( - ' ', - Color::Named(NamedColor::Foreground), - Color::Named(NamedColor::Background) - ) + Cell::new(' ', Color::Named(NamedColor::Foreground), Color::Named(NamedColor::Background)) } - } impl GridCell for Cell { @@ -130,13 +125,7 @@ impl Cell { } pub fn new(c: char, fg: Color, bg: Color) -> Cell { - Cell { - extra: [' '; MAX_ZEROWIDTH_CHARS], - c, - bg, - fg, - flags: Flags::empty(), - } + Cell { extra: [' '; MAX_ZEROWIDTH_CHARS], c, bg, fg, flags: Flags::empty() } } #[inline] diff --git a/src/term/color.rs b/src/term/color.rs index abd7527..39def61 100644 --- a/src/term/color.rs +++ b/src/term/color.rs @@ -1,5 +1,5 @@ -use std::ops::{Index, IndexMut, Mul}; use std::fmt; +use std::ops::{Index, IndexMut, Mul}; use crate::ansi; use crate::config::Colors; @@ -24,7 +24,7 @@ impl Mul for Rgb { let result = Rgb { r: (f32::from(self.r) * rhs).max(0.0).min(255.0) as u8, g: (f32::from(self.g) * rhs).max(0.0).min(255.0) as u8, - b: (f32::from(self.b) * rhs).max(0.0).min(255.0) as u8 + b: (f32::from(self.b) * rhs).max(0.0).min(255.0) as u8, }; trace!("Scaling RGB by {} from {:?} to {:?}", rhs, self, result); @@ -60,28 +60,26 @@ impl<'a> From<&'a Colors> for List { impl List { pub fn fill_named(&mut self, colors: &Colors) { // Normals - self[ansi::NamedColor::Black] = colors.normal.black; - self[ansi::NamedColor::Red] = colors.normal.red; - self[ansi::NamedColor::Green] = colors.normal.green; - self[ansi::NamedColor::Yellow] = colors.normal.yellow; - self[ansi::NamedColor::Blue] = colors.normal.blue; + self[ansi::NamedColor::Black] = colors.normal.black; + self[ansi::NamedColor::Red] = colors.normal.red; + self[ansi::NamedColor::Green] = colors.normal.green; + self[ansi::NamedColor::Yellow] = colors.normal.yellow; + self[ansi::NamedColor::Blue] = colors.normal.blue; self[ansi::NamedColor::Magenta] = colors.normal.magenta; - self[ansi::NamedColor::Cyan] = colors.normal.cyan; - self[ansi::NamedColor::White] = colors.normal.white; + self[ansi::NamedColor::Cyan] = colors.normal.cyan; + self[ansi::NamedColor::White] = colors.normal.white; // Brights - self[ansi::NamedColor::BrightBlack] = colors.bright.black; - self[ansi::NamedColor::BrightRed] = colors.bright.red; - self[ansi::NamedColor::BrightGreen] = colors.bright.green; - self[ansi::NamedColor::BrightYellow] = colors.bright.yellow; - self[ansi::NamedColor::BrightBlue] = colors.bright.blue; + self[ansi::NamedColor::BrightBlack] = colors.bright.black; + self[ansi::NamedColor::BrightRed] = colors.bright.red; + self[ansi::NamedColor::BrightGreen] = colors.bright.green; + self[ansi::NamedColor::BrightYellow] = colors.bright.yellow; + self[ansi::NamedColor::BrightBlue] = colors.bright.blue; self[ansi::NamedColor::BrightMagenta] = colors.bright.magenta; - self[ansi::NamedColor::BrightCyan] = colors.bright.cyan; - self[ansi::NamedColor::BrightWhite] = colors.bright.white; - self[ansi::NamedColor::BrightForeground] = colors - .primary - .bright_foreground - .unwrap_or(colors.primary.foreground); + self[ansi::NamedColor::BrightCyan] = colors.bright.cyan; + self[ansi::NamedColor::BrightWhite] = colors.bright.white; + self[ansi::NamedColor::BrightForeground] = + colors.primary.bright_foreground.unwrap_or(colors.primary.foreground); // Foreground and background self[ansi::NamedColor::Foreground] = colors.primary.foreground; @@ -89,36 +87,34 @@ impl List { // Foreground and background for custom cursor colors self[ansi::NamedColor::CursorText] = colors.cursor.text.unwrap_or_else(Rgb::default); - self[ansi::NamedColor::Cursor] = colors.cursor.cursor.unwrap_or_else(Rgb::default); + self[ansi::NamedColor::Cursor] = colors.cursor.cursor.unwrap_or_else(Rgb::default); // Dims - self[ansi::NamedColor::DimForeground] = colors - .primary - .dim_foreground - .unwrap_or(colors.primary.foreground * 0.66); + self[ansi::NamedColor::DimForeground] = + colors.primary.dim_foreground.unwrap_or(colors.primary.foreground * 0.66); match colors.dim { Some(ref dim) => { trace!("Using config-provided dim colors"); - self[ansi::NamedColor::DimBlack] = dim.black; - self[ansi::NamedColor::DimRed] = dim.red; - self[ansi::NamedColor::DimGreen] = dim.green; - self[ansi::NamedColor::DimYellow] = dim.yellow; - self[ansi::NamedColor::DimBlue] = dim.blue; + self[ansi::NamedColor::DimBlack] = dim.black; + self[ansi::NamedColor::DimRed] = dim.red; + self[ansi::NamedColor::DimGreen] = dim.green; + self[ansi::NamedColor::DimYellow] = dim.yellow; + self[ansi::NamedColor::DimBlue] = dim.blue; self[ansi::NamedColor::DimMagenta] = dim.magenta; - self[ansi::NamedColor::DimCyan] = dim.cyan; - self[ansi::NamedColor::DimWhite] = dim.white; - } + self[ansi::NamedColor::DimCyan] = dim.cyan; + self[ansi::NamedColor::DimWhite] = dim.white; + }, None => { trace!("Deriving dim colors from normal colors"); - self[ansi::NamedColor::DimBlack] = colors.normal.black * 0.66; - self[ansi::NamedColor::DimRed] = colors.normal.red * 0.66; - self[ansi::NamedColor::DimGreen] = colors.normal.green * 0.66; - self[ansi::NamedColor::DimYellow] = colors.normal.yellow * 0.66; - self[ansi::NamedColor::DimBlue] = colors.normal.blue * 0.66; + self[ansi::NamedColor::DimBlack] = colors.normal.black * 0.66; + self[ansi::NamedColor::DimRed] = colors.normal.red * 0.66; + self[ansi::NamedColor::DimGreen] = colors.normal.green * 0.66; + self[ansi::NamedColor::DimYellow] = colors.normal.yellow * 0.66; + self[ansi::NamedColor::DimBlue] = colors.normal.blue * 0.66; self[ansi::NamedColor::DimMagenta] = colors.normal.magenta * 0.66; - self[ansi::NamedColor::DimCyan] = colors.normal.cyan * 0.66; - self[ansi::NamedColor::DimWhite] = colors.normal.white * 0.66; - } + self[ansi::NamedColor::DimCyan] = colors.normal.cyan * 0.66; + self[ansi::NamedColor::DimWhite] = colors.normal.white * 0.66; + }, } } @@ -129,14 +125,13 @@ impl List { for g in 0..6 { for b in 0..6 { // Override colors 16..232 with the config (if present) - if let Some(indexed_color) = colors - .indexed_colors - .iter() - .find(|ic| ic.index == index as u8) + if let Some(indexed_color) = + colors.indexed_colors.iter().find(|ic| ic.index == index as u8) { self[index] = indexed_color.color; } else { - self[index] = Rgb { r: if r == 0 { 0 } else { r * 40 + 55 }, + self[index] = Rgb { + r: if r == 0 { 0 } else { r * 40 + 55 }, b: if b == 0 { 0 } else { b * 40 + 55 }, g: if g == 0 { 0 } else { g * 40 + 55 }, }; @@ -157,10 +152,8 @@ impl List { let color_index = 16 + 216 + i; // Override colors 232..256 with the config (if present) - if let Some(indexed_color) = colors - .indexed_colors - .iter() - .find(|ic| ic.index == color_index) + if let Some(indexed_color) = + colors.indexed_colors.iter().find(|ic| ic.index == color_index) { self[index] = indexed_color.color; index += 1; @@ -168,11 +161,7 @@ impl List { } let value = i * 10 + 8; - self[index] = Rgb { - r: value, - g: value, - b: value - }; + self[index] = Rgb { r: value, g: value, b: value }; index += 1; } diff --git a/src/term/mod.rs b/src/term/mod.rs index 8910504..5edef44 100644 --- a/src/term/mod.rs +++ b/src/term/mod.rs @@ -13,30 +13,32 @@ // limitations under the License. // //! Exports the `Term` type which is a high-level API for the Grid -use std::ops::{Range, Index, IndexMut, RangeInclusive}; -use std::{ptr, io, mem}; -use std::cmp::{min, max}; +use std::cmp::{max, min}; +use std::ops::{Index, IndexMut, Range, RangeInclusive}; use std::time::{Duration, Instant}; +use std::{io, mem, ptr}; use arraydeque::ArrayDeque; -use unicode_width::UnicodeWidthChar; use glutin::MouseCursor; +use unicode_width::UnicodeWidthChar; -use font::{self, Size}; -use crate::ansi::{self, Color, NamedColor, Attr, Handler, CharsetIndex, StandardCharset, CursorStyle}; +use crate::ansi::{ + self, Attr, CharsetIndex, Color, CursorStyle, Handler, NamedColor, StandardCharset, +}; +use crate::config::{Config, VisualBellAnimation}; use crate::grid::{ BidirectionalIterator, DisplayIter, Grid, GridCell, IndexRegion, Indexed, Scroll, - ViewportPosition + ViewportPosition, }; -use crate::index::{self, Point, Column, Line, IndexRange, Contains, Linear}; -use crate::selection::{self, Selection, Locations}; -use crate::config::{Config, VisualBellAnimation}; -use copypasta::{Clipboard, Load, Store}; +use crate::index::{self, Column, Contains, IndexRange, Line, Linear, Point}; use crate::input::FONT_SIZE_STEP; -use crate::url::{Url, UrlParser}; use crate::message_bar::MessageBuffer; +use crate::selection::{self, Locations, Selection}; +use crate::term::cell::{Cell, Flags, LineLength}; use crate::term::color::Rgb; -use crate::term::cell::{LineLength, Cell, Flags}; +use crate::url::{Url, UrlParser}; +use copypasta::{Clipboard, Load, Store}; +use font::{self, Size}; #[cfg(windows)] use crate::tty; @@ -139,10 +141,7 @@ impl Search for Term { impl selection::Dimensions for Term { fn dimensions(&self) -> Point { - Point { - col: self.grid.num_cols(), - line: self.grid.num_lines() - } + Point { col: self.grid.num_cols(), line: self.grid.num_lines() } } } @@ -200,7 +199,7 @@ impl<'a> RenderableCellsIter<'a> { (ViewportPosition::Below, ViewportPosition::Visible(end_line)) => { Some((grid.num_lines(), Column(0), end_line, loc.end.col)) }, - (ViewportPosition::Below, ViewportPosition::Above) => { + (ViewportPosition::Below, ViewportPosition::Above) => { Some((grid.num_lines(), Column(0), Line(0), Column(0))) }, _ => None, @@ -209,14 +208,8 @@ impl<'a> RenderableCellsIter<'a> { if let Some((start_line, start_col, end_line, end_col)) = locations { // start and end *lines* are swapped as we switch from buffer to // Line coordinates. - let mut end = Point { - line: start_line, - col: start_col, - }; - let mut start = Point { - line: end_line, - col: end_col, - }; + let mut end = Point { line: start_line, col: start_col }; + let mut start = Point { line: end_line, col: end_col }; if start > end { ::std::mem::swap(&mut start, &mut end); @@ -242,32 +235,31 @@ impl<'a> RenderableCellsIter<'a> { config, colors: &term.colors, cursor_cells: ArrayDeque::new(), - }.initialize(cursor_style) + } + .initialize(cursor_style) } fn push_cursor_cells(&mut self, original: Cell, cursor: Cell, wide: Cell) { // Prints the char under the cell if cursor is situated on a non-empty cell - self.cursor_cells.push_back(Indexed { - line: self.cursor.line, - column: self.cursor.col, - inner: original, - }).expect("won't exceed capacity"); + self.cursor_cells + .push_back(Indexed { line: self.cursor.line, column: self.cursor.col, inner: original }) + .expect("won't exceed capacity"); // Prints the cursor - self.cursor_cells.push_back(Indexed { - line: self.cursor.line, - column: self.cursor.col, - inner: cursor, - }).expect("won't exceed capacity"); + self.cursor_cells + .push_back(Indexed { line: self.cursor.line, column: self.cursor.col, inner: cursor }) + .expect("won't exceed capacity"); // If cursor is over a wide (2 cell size) character, // print the second cursor cell if self.is_wide_cursor(&cursor) { - self.cursor_cells.push_back(Indexed { - line: self.cursor.line, - column: self.cursor.col + 1, - inner: wide, - }).expect("won't exceed capacity"); + self.cursor_cells + .push_back(Indexed { + line: self.cursor.line, + column: self.cursor.col + 1, + inner: wide, + }) + .expect("won't exceed capacity"); } } @@ -321,11 +313,13 @@ impl<'a> RenderableCellsIter<'a> { /// Populates list of cursor cells with the original cell fn populate_no_cursor(&mut self) { - self.cursor_cells.push_back(Indexed { - line: self.cursor.line, - column: self.cursor.col, - inner: self.grid[self.cursor], - }).expect("won't exceed capacity"); + self.cursor_cells + .push_back(Indexed { + line: self.cursor.line, + column: self.cursor.col, + inner: self.grid[self.cursor], + }) + .expect("won't exceed capacity"); } fn initialize(mut self, cursor_style: CursorStyle) -> Self { @@ -342,7 +336,7 @@ impl<'a> RenderableCellsIter<'a> { }, CursorStyle::Underline => { self.populate_underline_cursor(); - } + }, } } else { self.populate_no_cursor(); @@ -361,37 +355,41 @@ impl<'a> RenderableCellsIter<'a> { match fg { Color::Spec(rgb) => rgb, Color::Named(ansi) => { - match (self.config.draw_bold_text_with_bright_colors(), cell.flags & Flags::DIM_BOLD) { + match ( + self.config.draw_bold_text_with_bright_colors(), + cell.flags & Flags::DIM_BOLD, + ) { // If no bright foreground is set, treat it like the BOLD flag doesn't exist (_, self::cell::Flags::DIM_BOLD) if ansi == NamedColor::Foreground && self.config.colors().primary.bright_foreground.is_none() => { self.colors[NamedColor::DimForeground] - } + }, // Draw bold text in bright colors *and* contains bold flag. - (true, self::cell::Flags::BOLD) => self.colors[ansi.to_bright()], + (true, self::cell::Flags::BOLD) => self.colors[ansi.to_bright()], // Cell is marked as dim and not bold - (_, self::cell::Flags::DIM) | - (false, self::cell::Flags::DIM_BOLD) => self.colors[ansi.to_dim()], + (_, self::cell::Flags::DIM) | (false, self::cell::Flags::DIM_BOLD) => { + self.colors[ansi.to_dim()] + }, // None of the above, keep original color. - _ => self.colors[ansi] + _ => self.colors[ansi], } }, Color::Indexed(idx) => { let idx = match ( self.config.draw_bold_text_with_bright_colors(), cell.flags & Flags::DIM_BOLD, - idx + idx, ) { - (true, self::cell::Flags::BOLD, 0..=7) => idx as usize + 8, - (false, self::cell::Flags::DIM, 8..=15) => idx as usize - 8, - (false, self::cell::Flags::DIM, 0..=7) => idx as usize + 260, + (true, self::cell::Flags::BOLD, 0..=7) => idx as usize + 8, + (false, self::cell::Flags::DIM, 8..=15) => idx as usize - 8, + (false, self::cell::Flags::DIM, 0..=7) => idx as usize + 260, _ => idx as usize, }; self.colors[idx] - } + }, } } @@ -399,7 +397,7 @@ impl<'a> RenderableCellsIter<'a> { fn compute_bg_alpha(&self, bg: Color) -> f32 { match bg { Color::Named(NamedColor::Background) => 0.0, - _ => 1.0 + _ => 1.0, } } @@ -435,8 +433,8 @@ impl<'a> Iterator for RenderableCellsIter<'a> { fn next(&mut self) -> Option { loop { // Handle cursor - let (cell, selected, highlighted) = if self.cursor_offset == self.inner.offset() && - self.inner.column() == self.cursor.col + let (cell, selected, highlighted) = if self.cursor_offset == self.inner.offset() + && self.inner.column() == self.cursor.col { // Cursor cell let mut cell = self.cursor_cells.pop_front().unwrap(); @@ -454,9 +452,8 @@ impl<'a> Iterator for RenderableCellsIter<'a> { let index = Linear::new(self.grid.num_cols(), cell.column, cell.line); - let selected = self.selection.as_ref() - .map(|range| range.contains_(index)) - .unwrap_or(false); + let selected = + self.selection.as_ref().map(|range| range.contains_(index)).unwrap_or(false); // Skip empty cells if cell.is_empty() && !selected { @@ -464,7 +461,9 @@ impl<'a> Iterator for RenderableCellsIter<'a> { } // Underline URL highlights - let highlighted = self.url_highlight.as_ref() + let highlighted = self + .url_highlight + .as_ref() .map(|range| range.contains_(index)) .unwrap_or(false); @@ -506,10 +505,9 @@ impl<'a> Iterator for RenderableCellsIter<'a> { bg: bg_rgb, bg_alpha, flags, - }) + }); } } - } pub mod mode { @@ -558,41 +556,40 @@ impl CharsetMapping for StandardCharset { fn map(&self, c: char) -> char { match *self { StandardCharset::Ascii => c, - StandardCharset::SpecialCharacterAndLineDrawing => - match c { - '`' => '◆', - 'a' => '▒', - 'b' => '\t', - 'c' => '\u{000c}', - 'd' => '\r', - 'e' => '\n', - 'f' => '°', - 'g' => '±', - 'h' => '\u{2424}', - 'i' => '\u{000b}', - 'j' => '┘', - 'k' => '┐', - 'l' => '┌', - 'm' => '└', - 'n' => '┼', - 'o' => '⎺', - 'p' => '⎻', - 'q' => '─', - 'r' => '⎼', - 's' => '⎽', - 't' => '├', - 'u' => '┤', - 'v' => '┴', - 'w' => '┬', - 'x' => '│', - 'y' => '≤', - 'z' => '≥', - '{' => 'π', - '|' => '≠', - '}' => '£', - '~' => '·', - _ => c - }, + StandardCharset::SpecialCharacterAndLineDrawing => match c { + '`' => '◆', + 'a' => '▒', + 'b' => '\t', + 'c' => '\u{000c}', + 'd' => '\r', + 'e' => '\n', + 'f' => '°', + 'g' => '±', + 'h' => '\u{2424}', + 'i' => '\u{000b}', + 'j' => '┘', + 'k' => '┐', + 'l' => '┌', + 'm' => '└', + 'n' => '┼', + 'o' => '⎺', + 'p' => '⎻', + 'q' => '─', + 'r' => '⎼', + 's' => '⎽', + 't' => '├', + 'u' => '┤', + 'v' => '┴', + 'w' => '┬', + 'x' => '│', + 'y' => '≤', + 'z' => '≥', + '{' => 'π', + '|' => '≠', + '}' => '£', + '~' => '·', + _ => c, + }, } } } @@ -602,6 +599,7 @@ struct Charsets([StandardCharset; 4]); impl Index for Charsets { type Output = StandardCharset; + fn index(&self, index: CharsetIndex) -> &StandardCharset { &self.0[index as usize] } @@ -637,10 +635,10 @@ pub struct VisualBell { } fn cubic_bezier(p0: f64, p1: f64, p2: f64, p3: f64, x: f64) -> f64 { - (1.0 - x).powi(3) * p0 + - 3.0 * (1.0 - x).powi(2) * x * p1 + - 3.0 * (1.0 - x) * x.powi(2) * p2 + - x.powi(3) * p3 + (1.0 - x).powi(3) * p0 + + 3.0 * (1.0 - x).powi(2) * x * p1 + + 3.0 * (1.0 - x) * x.powi(2) * p2 + + x.powi(3) * p3 } impl VisualBell { @@ -675,7 +673,7 @@ impl VisualBell { } false }, - None => true + None => true, } } @@ -703,10 +701,10 @@ impl VisualBell { } let elapsed = instant.duration_since(earlier); - let elapsed_f = elapsed.as_secs() as f64 + - f64::from(elapsed.subsec_nanos()) / 1e9f64; - let duration_f = self.duration.as_secs() as f64 + - f64::from(self.duration.subsec_nanos()) / 1e9f64; + let elapsed_f = + elapsed.as_secs() as f64 + f64::from(elapsed.subsec_nanos()) / 1e9f64; + let duration_f = self.duration.as_secs() as f64 + + f64::from(self.duration.subsec_nanos()) / 1e9f64; // Otherwise, we compute a value `time` from 0.0 to 1.0 // inclusive that represents the ratio of `elapsed` time to the @@ -722,7 +720,9 @@ impl VisualBell { }, 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::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), @@ -733,7 +733,7 @@ impl VisualBell { // Since we want the `intensity` of the VisualBell to decay over // `time`, we subtract the `inverse_intensity` from 1.0. 1.0 - inverse_intensity - } + }, } } @@ -890,12 +890,11 @@ impl SizeInfo { Point { line: min(line, Line(self.lines().saturating_sub(1))), - col: min(col, Column(self.cols().saturating_sub(1))) + col: min(col, Column(self.cols().saturating_sub(1))), } } } - impl Term { pub fn selection(&self) -> &Option { &self.grid.selection @@ -997,8 +996,7 @@ impl Term { self.default_cursor_style = config.cursor_style(); self.dynamic_title = config.dynamic_title(); self.auto_scroll = config.scrolling().auto_scroll; - self.grid - .update_history(config.scrolling().history as usize, &self.cursor.template); + self.grid.update_history(config.scrolling().history as usize, &self.cursor.template); } #[inline] @@ -1011,7 +1009,9 @@ impl Term { trait PushChar { fn push_char(&mut self, c: char); fn maybe_newline(&mut self, grid: &Grid, line: usize, ending: Column) { - if ending != Column(0) && !grid[line][ending - 1].flags.contains(cell::Flags::WRAPLINE) { + if ending != Column(0) + && !grid[line][ending - 1].flags.contains(cell::Flags::WRAPLINE) + { self.push_char('\n'); } } @@ -1026,7 +1026,7 @@ impl Term { use std::ops::Range; - trait Append : PushChar { + trait Append: PushChar { fn append( &mut self, grid: &Grid, @@ -1042,7 +1042,7 @@ impl Term { grid: &Grid, tabs: &TabStops, mut line: usize, - cols: Range + cols: Range, ) { // Select until last line still within the buffer line = min(line, grid.len() - 1); @@ -1115,7 +1115,6 @@ impl Term { // Starting line res.append(&self.grid, &self.tabs, start.line, Column(0)..start.col); - }, // Multi line selection @@ -1130,7 +1129,7 @@ impl Term { // Starting line res.append(&self.grid, &self.tabs, start.line, Column(0)..start.col); - } + }, } Some(res) @@ -1180,11 +1179,12 @@ impl Term { window_focused: bool, ) -> RenderableCellsIter<'_> { let alt_screen = self.mode.contains(TermMode::ALT_SCREEN); - let selection = self.grid.selection.as_ref() + let selection = self + .grid + .selection + .as_ref() .and_then(|s| s.to_span(self, alt_screen)) - .map(|span| { - span.to_locations() - }); + .map(|span| span.to_locations()); let cursor = if window_focused || !config.unfocused_hollow_cursor() { self.cursor_style.unwrap_or(self.default_cursor_style) @@ -1192,12 +1192,7 @@ impl Term { CursorStyle::HollowBlock }; - RenderableCellsIter::new( - &self, - config, - selection, - cursor, - ) + RenderableCellsIter::new(&self, config, selection, cursor) } /// Resize terminal to new dimensions @@ -1205,8 +1200,8 @@ impl Term { debug!("Resizing terminal"); // Bounds check; lots of math assumes width and height are > 0 - if size.width as usize <= 2 * self.size_info.padding_x as usize || - size.height as usize <= 2 * self.size_info.padding_y as usize + if size.width as usize <= 2 * self.size_info.padding_x as usize + || size.height as usize <= 2 * self.size_info.padding_y as usize { return; } @@ -1455,10 +1450,7 @@ impl ansi::Handler for Term { trace!("Wrapping input"); { - let location = Point { - line: self.cursor.point.line, - col: self.cursor.point.col - }; + let location = Point { line: self.cursor.point.line, col: self.cursor.point.col }; let cell = &mut self.grid[&location]; cell.flags.insert(cell::Flags::WRAPLINE); @@ -1498,8 +1490,7 @@ impl ansi::Handler for Term { if width == 0 { let col = self.cursor.point.col.0.saturating_sub(1); let line = self.cursor.point.line; - if self.grid[line][Column(col)].flags.contains(cell::Flags::WIDE_CHAR_SPACER) - { + if self.grid[line][Column(col)].flags.contains(cell::Flags::WIDE_CHAR_SPACER) { col.saturating_sub(1); } self.grid[line][Column(col)].push_extra(c); @@ -1536,8 +1527,7 @@ impl ansi::Handler for Term { let mut template = self.cursor.template; template.c = 'E'; - self.grid.region_mut(..) - .each(|c| c.reset(&template)); + self.grid.region_mut(..).each(|c| c.reset(&template)); } #[inline] @@ -1858,11 +1848,7 @@ impl ansi::Handler for Term { #[inline] fn save_cursor_position(&mut self) { trace!("Saving cursor position"); - let cursor = if self.alt { - &mut self.cursor_save_alt - } else { - &mut self.cursor_save - }; + let cursor = if self.alt { &mut self.cursor_save_alt } else { &mut self.cursor_save }; *cursor = self.cursor; } @@ -1870,11 +1856,7 @@ impl ansi::Handler for Term { #[inline] fn restore_cursor_position(&mut self) { trace!("Restoring cursor position"); - let source = if self.alt { - &self.cursor_save_alt - } else { - &self.cursor_save - }; + let source = if self.alt { &self.cursor_save_alt } else { &self.cursor_save }; self.cursor = *source; self.cursor.point.line = min(self.cursor.point.line, self.grid.num_lines() - 1); @@ -1887,7 +1869,7 @@ impl ansi::Handler for Term { let mut template = self.cursor.template; template.flags ^= template.flags; - let col = self.cursor.point.col; + let col = self.cursor.point.col; match mode { ansi::LineClearMode::Right => { @@ -1929,13 +1911,12 @@ impl ansi::Handler for Term { /// Set the clipboard #[inline] - fn set_clipboard(&mut self, string: &str) - { - Clipboard::new() - .and_then(|mut clipboard| clipboard.store_primary(string)) - .unwrap_or_else(|err| { + fn set_clipboard(&mut self, string: &str) { + Clipboard::new().and_then(|mut clipboard| clipboard.store_primary(string)).unwrap_or_else( + |err| { warn!("Error storing selection to clipboard: {}", err); - }); + }, + ); } #[inline] @@ -1954,7 +1935,8 @@ impl ansi::Handler for Term { cell.reset(&template); } if self.cursor.point.line < self.grid.num_lines() - 1 { - self.grid.region_mut((self.cursor.point.line + 1)..) + self.grid + .region_mut((self.cursor.point.line + 1)..) .each(|cell| cell.reset(&template)); } }, @@ -1963,7 +1945,8 @@ impl ansi::Handler for Term { // If clearing more than one line if self.cursor.point.line > Line(1) { // Fully clear all lines before the current line - self.grid.region_mut(..self.cursor.point.line) + self.grid + .region_mut(..self.cursor.point.line) .each(|cell| cell.reset(&template)); } // Clear up to the current column in the current line @@ -1987,7 +1970,7 @@ impl ansi::Handler for Term { }, ansi::TabulationClearMode::All => { self.tabs.clear_all(); - } + }, } } @@ -2042,7 +2025,9 @@ impl ansi::Handler for Term { Attr::Bold => self.cursor.template.flags.insert(cell::Flags::BOLD), Attr::CancelBold => self.cursor.template.flags.remove(cell::Flags::BOLD), Attr::Dim => self.cursor.template.flags.insert(cell::Flags::DIM), - Attr::CancelBoldDim => self.cursor.template.flags.remove(cell::Flags::BOLD | cell::Flags::DIM), + Attr::CancelBoldDim => { + self.cursor.template.flags.remove(cell::Flags::BOLD | cell::Flags::DIM) + }, Attr::Italic => self.cursor.template.flags.insert(cell::Flags::ITALIC), Attr::CancelItalic => self.cursor.template.flags.remove(cell::Flags::ITALIC), Attr::Underscore => self.cursor.template.flags.insert(cell::Flags::UNDERLINE), @@ -2053,7 +2038,7 @@ impl ansi::Handler for Term { Attr::CancelStrike => self.cursor.template.flags.remove(cell::Flags::STRIKEOUT), _ => { debug!("Term got unhandled attr: {:?}", attr); - } + }, } } @@ -2093,12 +2078,12 @@ impl ansi::Handler for Term { ansi::Mode::Insert => self.mode.insert(mode::TermMode::INSERT), // heh ansi::Mode::BlinkingCursor => { trace!("... unimplemented mode"); - } + }, } } #[inline] - fn unset_mode(&mut self,mode: ansi::Mode) { + fn unset_mode(&mut self, mode: ansi::Mode) { trace!("Unsetting mode: {:?}", mode); match mode { ansi::Mode::SwapScreenAndSetRestoreCursor => { @@ -2133,7 +2118,7 @@ impl ansi::Handler for Term { ansi::Mode::Insert => self.mode.remove(mode::TermMode::INSERT), ansi::Mode::BlinkingCursor => { trace!("... unimplemented mode"); - } + }, } } @@ -2177,7 +2162,7 @@ impl ansi::Handler for Term { } struct TabStops { - tabs: Vec + tabs: Vec, } impl TabStops { @@ -2185,7 +2170,7 @@ impl TabStops { TabStops { tabs: IndexRange::from(Column(0)..num_cols) .map(|i| (*i as usize) % tabspaces == 0) - .collect::>() + .collect::>(), } } @@ -2214,18 +2199,18 @@ impl IndexMut for TabStops { mod tests { use serde_json; - use super::{Cell, Term, SizeInfo}; + use super::{Cell, SizeInfo, Term}; use crate::term::cell; - use crate::grid::{Grid, Scroll}; - use crate::index::{Point, Line, Column, Side}; - use crate::ansi::{self, Handler, CharsetIndex, StandardCharset}; - use crate::selection::Selection; - use std::mem; - use crate::input::FONT_SIZE_STEP; - use font::Size; + use crate::ansi::{self, CharsetIndex, Handler, StandardCharset}; use crate::config::Config; + use crate::grid::{Grid, Scroll}; + use crate::index::{Column, Line, Point, Side}; + use crate::input::FONT_SIZE_STEP; use crate::message_bar::MessageBuffer; + use crate::selection::Selection; + use font::Size; + use std::mem; #[test] fn semantic_selection_works() { @@ -2290,7 +2275,6 @@ mod tests { grid[Line(0)][Column(0)].c = '"'; grid[Line(0)][Column(3)].c = '"'; - mem::swap(&mut term.grid, &mut grid); *term.selection_mut() = Some(Selection::lines(Point { line: 0, col: Column(3) })); @@ -2336,8 +2320,7 @@ mod tests { let grid: Grid = Grid::new(Line(24), Column(80), 0, template); let serialized = serde_json::to_string(&grid).expect("ser"); - let deserialized = serde_json::from_str::>(&serialized) - .expect("de"); + let deserialized = serde_json::from_str::>(&serialized).expect("de"); assert_eq!(deserialized, grid); } @@ -2355,8 +2338,7 @@ mod tests { }; let mut term = Term::new(&Default::default(), size, MessageBuffer::new()); let cursor = Point::new(Line(0), Column(0)); - term.configure_charset(CharsetIndex::G0, - StandardCharset::SpecialCharacterAndLineDrawing); + term.configure_charset(CharsetIndex::G0, StandardCharset::SpecialCharacterAndLineDrawing); term.input('a'); assert_eq!(term.grid()[&cursor].c, '▒'); @@ -2440,7 +2422,7 @@ mod tests { cell_height: 3.0, padding_x: 0.0, padding_y: 0.0, - dpr: 1.0 + dpr: 1.0, }; let config: Config = Default::default(); let mut term: Term = Term::new(&config, size, MessageBuffer::new()); @@ -2460,27 +2442,27 @@ mod tests { #[cfg(all(test, feature = "bench"))] mod benches { - extern crate test; extern crate serde_json as json; + extern crate test; - use std::io::Read; use std::fs::File; + use std::io::Read; use std::mem; use std::path::Path; - use crate::grid::Grid; use crate::config::Config; + use crate::grid::Grid; use crate::message_bar::MessageBuffer; - use super::{SizeInfo, Term}; use super::cell::Cell; + use super::{SizeInfo, Term}; fn read_string

(path: P) -> String - where P: AsRef + where + P: AsRef, { let mut res = String::new(); - File::open(path.as_ref()).unwrap() - .read_to_string(&mut res).unwrap(); + File::open(path.as_ref()).unwrap().read_to_string(&mut res).unwrap(); res } @@ -2497,12 +2479,14 @@ mod benches { #[bench] fn render_iter(b: &mut test::Bencher) { // Need some realistic grid state; using one of the ref files. - let serialized_grid = read_string( - concat!(env!("CARGO_MANIFEST_DIR"), "/tests/ref/vim_large_window_scroll/grid.json") - ); - let serialized_size = read_string( - concat!(env!("CARGO_MANIFEST_DIR"), "/tests/ref/vim_large_window_scroll/size.json") - ); + let serialized_grid = read_string(concat!( + env!("CARGO_MANIFEST_DIR"), + "/tests/ref/vim_large_window_scroll/grid.json" + )); + let serialized_size = read_string(concat!( + env!("CARGO_MANIFEST_DIR"), + "/tests/ref/vim_large_window_scroll/size.json" + )); let mut grid: Grid = json::from_str(&serialized_grid).unwrap(); let size: SizeInfo = json::from_str(&serialized_size).unwrap(); diff --git a/src/tty/mod.rs b/src/tty/mod.rs index ea2dd0c..ec175ee 100644 --- a/src/tty/mod.rs +++ b/src/tty/mod.rs @@ -57,7 +57,7 @@ pub trait EventedReadWrite { #[derive(PartialEq)] pub enum ChildEvent { /// Indicates the child has exited - Exited + Exited, } /// A pseudoterminal (or PTY) @@ -65,7 +65,7 @@ pub enum ChildEvent { /// This is a refinement of EventedReadWrite that also provides a channel through which we can be /// notified if the PTY child process does something we care about (other than writing to the TTY). /// In particular, this allows for race-free child exit notification on UNIX (cf. `SIGCHLD`). -pub trait EventedPty : EventedReadWrite { +pub trait EventedPty: EventedReadWrite { #[cfg(unix)] fn child_event_token(&self) -> mio::Token; @@ -83,11 +83,7 @@ pub fn setup_env(config: &Config) { // below. env::set_var( "TERM", - if Database::from_name("alacritty").is_ok() { - "alacritty" - } else { - "xterm-256color" - }, + if Database::from_name("alacritty").is_ok() { "alacritty" } else { "xterm-256color" }, ); // Advertise 24-bit color support diff --git a/src/tty/unix.rs b/src/tty/unix.rs index d8392dc..0e3dc2f 100644 --- a/src/tty/unix.rs +++ b/src/tty/unix.rs @@ -15,24 +15,27 @@ //! tty related functionality //! -use crate::tty::{EventedReadWrite, EventedPty, ChildEvent}; -use crate::term::SizeInfo; -use crate::display::OnResize; -use crate::config::{Config, Shell}; use crate::cli::Options; +use crate::config::{Config, Shell}; +use crate::display::OnResize; +use crate::term::SizeInfo; +use crate::tty::{ChildEvent, EventedPty, EventedReadWrite}; use mio; use libc::{self, c_int, pid_t, winsize, TIOCSCTTY}; use nix::pty::openpty; use signal_hook::{self as sighook, iterator::Signals}; -use std::os::unix::{process::CommandExt, io::{FromRawFd, AsRawFd, RawFd}}; -use std::fs::File; -use std::process::{Command, Stdio, Child}; -use std::ffi::CStr; -use std::ptr; use mio::unix::EventedFd; +use std::ffi::CStr; +use std::fs::File; use std::io; +use std::os::unix::{ + io::{AsRawFd, FromRawFd, RawFd}, + process::CommandExt, +}; +use std::process::{Child, Command, Stdio}; +use std::ptr; use std::sync::atomic::{AtomicUsize, Ordering}; /// Process ID of child process @@ -55,8 +58,7 @@ fn make_pty(size: winsize) -> (RawFd, RawFd) { win_size.ws_xpixel = 0; win_size.ws_ypixel = 0; - let ends = openpty(Some(&win_size), None) - .expect("openpty failed"); + let ends = openpty(Some(&win_size), None).expect("openpty failed"); (ends.master, ends.slave) } @@ -134,7 +136,6 @@ pub struct Pty { token: mio::Token, signals: Signals, signals_token: mio::Token, - } impl Pty { @@ -145,9 +146,7 @@ impl Pty { pub fn resize(&self, size: &T) { let win = size.to_winsize(); - let res = unsafe { - libc::ioctl(self.fd.as_raw_fd(), libc::TIOCSWINSZ, &win as *const _) - }; + let res = unsafe { libc::ioctl(self.fd.as_raw_fd(), libc::TIOCSWINSZ, &win as *const _) }; if res < 0 { die!("ioctl TIOCSWINSZ failed: {}", errno()); @@ -170,10 +169,7 @@ pub fn new( let default_shell = if cfg!(target_os = "macos") { let shell_name = pw.shell.rsplit('/').next().unwrap(); - let argv = vec![ - String::from("-c"), - format!("exec -a -{} {}", shell_name, pw.shell), - ]; + let argv = vec![String::from("-c"), format!("exec -a -{} {}", shell_name, pw.shell)]; Shell::new_with_args("/bin/bash", argv) } else { @@ -265,7 +261,7 @@ pub fn new( }, Err(err) => { die!("Failed to spawn command: {}", err); - } + }, } } @@ -282,19 +278,14 @@ impl EventedReadWrite for Pty { poll_opts: mio::PollOpt, ) -> io::Result<()> { self.token = token.next().unwrap(); - poll.register( - &EventedFd(&self.fd.as_raw_fd()), - self.token, - interest, - poll_opts - )?; + poll.register(&EventedFd(&self.fd.as_raw_fd()), self.token, interest, poll_opts)?; self.signals_token = token.next().unwrap(); poll.register( &self.signals, self.signals_token, mio::Ready::readable(), - mio::PollOpt::level() + mio::PollOpt::level(), ) } @@ -303,20 +294,15 @@ impl EventedReadWrite for Pty { &mut self, poll: &mio::Poll, interest: mio::Ready, - poll_opts: mio::PollOpt + poll_opts: mio::PollOpt, ) -> io::Result<()> { - poll.reregister( - &EventedFd(&self.fd.as_raw_fd()), - self.token, - interest, - poll_opts - )?; + poll.reregister(&EventedFd(&self.fd.as_raw_fd()), self.token, interest, poll_opts)?; poll.reregister( &self.signals, self.signals_token, mio::Ready::readable(), - mio::PollOpt::level() + mio::PollOpt::level(), ) } @@ -350,23 +336,20 @@ impl EventedReadWrite for Pty { impl EventedPty for Pty { #[inline] fn next_child_event(&mut self) -> Option { - self.signals - .pending() - .next() - .and_then(|signal| { - if signal != sighook::SIGCHLD { - return None; - } + self.signals.pending().next().and_then(|signal| { + if signal != sighook::SIGCHLD { + return None; + } - match self.child.try_wait() { - Err(e) => { - error!("Error checking child process termination: {}", e); - None - }, - Ok(None) => None, - Ok(_) => Some(ChildEvent::Exited), - } - }) + match self.child.try_wait() { + Err(e) => { + error!("Error checking child process termination: {}", e); + None + }, + Ok(None) => None, + Ok(_) => Some(ChildEvent::Exited), + } + }) } #[inline] @@ -400,9 +383,7 @@ impl OnResize for i32 { fn on_resize(&mut self, size: &SizeInfo) { let win = size.to_winsize(); - let res = unsafe { - libc::ioctl(*self, libc::TIOCSWINSZ, &win as *const _) - }; + let res = unsafe { libc::ioctl(*self, libc::TIOCSWINSZ, &win as *const _) }; if res < 0 { die!("ioctl TIOCSWINSZ failed: {}", errno()); diff --git a/src/tty/windows/conpty.rs b/src/tty/windows/conpty.rs index 6c74df7..7383118 100644 --- a/src/tty/windows/conpty.rs +++ b/src/tty/windows/conpty.rs @@ -214,10 +214,7 @@ pub fn new<'a>( cmdline.insert(0, initial_command.program().into()); // Warning, here be borrow hell - let cwd = options - .working_dir - .as_ref() - .map(|dir| canonicalize(dir).unwrap()); + let cwd = options.working_dir.as_ref().map(|dir| canonicalize(dir).unwrap()); let cwd = cwd.as_ref().map(|dir| dir.to_str().unwrap()); // Create the client application, using startup info containing ConPTY info @@ -250,10 +247,7 @@ pub fn new<'a>( let conin = EventedAnonWrite::new(conin); let conout = EventedAnonRead::new(conout); - let agent = Conpty { - handle: pty_handle, - api, - }; + let agent = Conpty { handle: pty_handle, api }; Some(Pty { handle: super::PtyHandle::Conpty(ConptyHandle::new(agent)), @@ -279,10 +273,7 @@ fn coord_from_sizeinfo(sizeinfo: &SizeInfo) -> Option { let lines = sizeinfo.lines().0; if cols <= i16::MAX as usize && lines <= i16::MAX as usize { - Some(COORD { - X: sizeinfo.cols().0 as i16, - Y: sizeinfo.lines().0 as i16, - }) + Some(COORD { X: sizeinfo.cols().0 as i16, Y: sizeinfo.lines().0 as i16 }) } else { None } diff --git a/src/tty/windows/mod.rs b/src/tty/windows/mod.rs index 2f5caa9..c87c525 100644 --- a/src/tty/windows/mod.rs +++ b/src/tty/windows/mod.rs @@ -28,7 +28,7 @@ use crate::cli::Options; use crate::config::Config; use crate::display::OnResize; use crate::term::SizeInfo; -use crate::tty::{EventedReadWrite, EventedPty}; +use crate::tty::{EventedPty, EventedReadWrite}; mod conpty; mod winpty; @@ -44,14 +44,14 @@ pub fn process_should_exit() -> bool { WAIT_OBJECT_0 => { info!("wait_object_0"); true - } + }, // Reached timeout of 0, process has not exited WAIT_TIMEOUT => false, // Error checking process, winpty gave us a bad agent handle? _ => { info!("Bad exit: {}", ::std::io::Error::last_os_error()); true - } + }, } } } @@ -219,7 +219,7 @@ impl<'a> OnResize for PtyHandle<'a> { PtyHandle::Conpty(c) => { let mut handle = c.clone(); handle.on_resize(sizeinfo) - } + }, } } } @@ -240,34 +240,14 @@ impl<'a> EventedReadWrite for Pty<'a> { self.write_token = token.next().unwrap(); if interest.is_readable() { - poll.register( - &self.conout, - self.read_token, - mio::Ready::readable(), - poll_opts, - )? + poll.register(&self.conout, self.read_token, mio::Ready::readable(), poll_opts)? } else { - poll.register( - &self.conout, - self.read_token, - mio::Ready::empty(), - poll_opts, - )? + poll.register(&self.conout, self.read_token, mio::Ready::empty(), poll_opts)? } if interest.is_writable() { - poll.register( - &self.conin, - self.write_token, - mio::Ready::writable(), - poll_opts, - )? + poll.register(&self.conin, self.write_token, mio::Ready::writable(), poll_opts)? } else { - poll.register( - &self.conin, - self.write_token, - mio::Ready::empty(), - poll_opts, - )? + poll.register(&self.conin, self.write_token, mio::Ready::empty(), poll_opts)? } Ok(()) } @@ -280,34 +260,14 @@ impl<'a> EventedReadWrite for Pty<'a> { poll_opts: mio::PollOpt, ) -> io::Result<()> { if interest.is_readable() { - poll.reregister( - &self.conout, - self.read_token, - mio::Ready::readable(), - poll_opts, - )?; + poll.reregister(&self.conout, self.read_token, mio::Ready::readable(), poll_opts)?; } else { - poll.reregister( - &self.conout, - self.read_token, - mio::Ready::empty(), - poll_opts, - )?; + poll.reregister(&self.conout, self.read_token, mio::Ready::empty(), poll_opts)?; } if interest.is_writable() { - poll.reregister( - &self.conin, - self.write_token, - mio::Ready::writable(), - poll_opts, - )?; + poll.reregister(&self.conin, self.write_token, mio::Ready::writable(), poll_opts)?; } else { - poll.reregister( - &self.conin, - self.write_token, - mio::Ready::empty(), - poll_opts, - )?; + poll.reregister(&self.conin, self.write_token, mio::Ready::empty(), poll_opts)?; } Ok(()) } @@ -340,4 +300,4 @@ impl<'a> EventedReadWrite for Pty<'a> { } } -impl<'a> EventedPty for Pty<'a> { } +impl<'a> EventedPty for Pty<'a> {} diff --git a/src/tty/windows/winpty.rs b/src/tty/windows/winpty.rs index 26536ee..10bd9d0 100644 --- a/src/tty/windows/winpty.rs +++ b/src/tty/windows/winpty.rs @@ -14,29 +14,29 @@ use super::{Pty, HANDLE}; -use std::io; use std::fs::OpenOptions; -use std::os::windows::io::{FromRawHandle, IntoRawHandle}; +use std::io; use std::os::windows::fs::OpenOptionsExt; +use std::os::windows::io::{FromRawHandle, IntoRawHandle}; use std::sync::Arc; use std::u16; use dunce::canonicalize; use mio_named_pipes::NamedPipe; use winapi::um::winbase::FILE_FLAG_OVERLAPPED; -use winpty::{ConfigFlags, MouseMode, SpawnConfig, SpawnFlags, Winpty}; use winpty::Config as WinptyConfig; +use winpty::{ConfigFlags, MouseMode, SpawnConfig, SpawnFlags, Winpty}; +use crate::cli::Options; use crate::config::{Config, Shell}; use crate::display::OnResize; -use crate::cli::Options; use crate::term::SizeInfo; // We store a raw pointer because we need mutable access to call // on_resize from a separate thread. Winpty internally uses a mutex // so this is safe, despite outwards appearance. pub struct Agent<'a> { - winpty: *mut Winpty<'a> + winpty: *mut Winpty<'a>, } /// Handle can be cloned freely and moved between threads. @@ -48,9 +48,7 @@ unsafe impl<'a> Sync for Agent<'a> {} impl<'a> Agent<'a> { pub fn new(winpty: Winpty<'a>) -> Self { - Self { - winpty: Box::into_raw(Box::new(winpty)) - } + Self { winpty: Box::into_raw(Box::new(winpty)) } } /// Get immutable access to Winpty. @@ -68,11 +66,12 @@ impl<'a> Agent<'a> { impl<'a> Drop for Agent<'a> { fn drop(&mut self) { - unsafe { Box::from_raw(self.winpty); } + unsafe { + Box::from_raw(self.winpty); + } } } - /// How long the winpty agent should wait for any RPC request /// This is a placeholder value until we see how often long responses happen const AGENT_TIMEOUT: u32 = 10000; @@ -112,30 +111,19 @@ pub fn new<'a>( Some(&cmdline.join(" ")), cwd, None, // Env - ).unwrap(); + ) + .unwrap(); let default_opts = &mut OpenOptions::new(); - default_opts - .share_mode(0) - .custom_flags(FILE_FLAG_OVERLAPPED); + default_opts.share_mode(0).custom_flags(FILE_FLAG_OVERLAPPED); let (conout_pipe, conin_pipe); unsafe { conout_pipe = NamedPipe::from_raw_handle( - default_opts - .clone() - .read(true) - .open(conout) - .unwrap() - .into_raw_handle(), + default_opts.clone().read(true).open(conout).unwrap().into_raw_handle(), ); conin_pipe = NamedPipe::from_raw_handle( - default_opts - .clone() - .write(true) - .open(conin) - .unwrap() - .into_raw_handle(), + default_opts.clone().write(true).open(conin).unwrap().into_raw_handle(), ); }; @@ -166,7 +154,7 @@ pub fn new<'a>( conout: super::EventedReadablePipe::Named(conout_pipe), conin: super::EventedWritablePipe::Named(conin_pipe), read_token: 0.into(), - write_token: 0.into() + write_token: 0.into(), } } diff --git a/src/url.rs b/src/url.rs index 3366519..d3caf9f 100644 --- a/src/url.rs +++ b/src/url.rs @@ -12,17 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -use url; use unicode_width::UnicodeWidthChar; +use url; use crate::term::cell::{Cell, Flags}; // See https://tools.ietf.org/html/rfc3987#page-13 const URL_SEPARATOR_CHARS: [char; 10] = ['<', '>', '"', ' ', '{', '}', '|', '\\', '^', '`']; const URL_DENY_END_CHARS: [char; 8] = ['.', ',', ';', ':', '?', '!', '/', '(']; -const URL_SCHEMES: [&str; 8] = [ - "http", "https", "mailto", "news", "file", "git", "ssh", "ftp", -]; +const URL_SCHEMES: [&str; 8] = ["http", "https", "mailto", "news", "file", "git", "ssh", "ftp"]; /// URL text and origin of the original click position. #[derive(Debug, PartialEq)] @@ -39,10 +37,7 @@ pub struct UrlParser { impl UrlParser { pub fn new() -> Self { - UrlParser { - state: String::new(), - origin: 0, - } + UrlParser { state: String::new(), origin: 0 } } /// Advance the parser one character to the left. @@ -74,19 +69,17 @@ impl UrlParser { // Remove non-alphabetical characters before the scheme // https://tools.ietf.org/html/rfc3986#section-3.1 if let Some(index) = self.state.find("://") { - let iter = self - .state - .char_indices() - .rev() - .skip_while(|(byte_index, _)| *byte_index >= index); + let iter = + self.state.char_indices().rev().skip_while(|(byte_index, _)| *byte_index >= index); for (byte_index, c) in iter { match c { 'a'...'z' | 'A'...'Z' => (), _ => { - self.origin = self.origin.saturating_sub(byte_index + c.width().unwrap_or(1)); + self.origin = + self.origin.saturating_sub(byte_index + c.width().unwrap_or(1)); self.state = self.state.split_off(byte_index + c.len_utf8()); break; - } + }, } } } @@ -103,7 +96,7 @@ impl UrlParser { ')' | ']' => { self.state.truncate(i); break; - } + }, _ => (), } } @@ -127,14 +120,11 @@ impl UrlParser { match url::Url::parse(&self.state) { Ok(url) => { if URL_SCHEMES.contains(&url.scheme()) && self.origin > 0 { - Some(Url { - origin: self.origin - 1, - text: self.state, - }) + Some(Url { origin: self.origin - 1, text: self.state }) } else { None } - } + }, Err(_) => None, } } @@ -160,9 +150,9 @@ mod tests { use crate::grid::Grid; use crate::index::{Column, Line, Point}; - use crate::term::{Search, SizeInfo, Term}; - use crate::term::cell::{Cell, Flags}; use crate::message_bar::MessageBuffer; + use crate::term::cell::{Cell, Flags}; + use crate::term::{Search, SizeInfo, Term}; fn url_create_term(input: &str) -> Term { let size = SizeInfo { diff --git a/src/util.rs b/src/util.rs index 4532d2e..06e8436 100644 --- a/src/util.rs +++ b/src/util.rs @@ -12,10 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::{cmp, io}; use std::ffi::OsStr; use std::process::Command; use std::process::Stdio; +use std::{cmp, io}; #[cfg(not(windows))] use std::os::unix::process::CommandExt; @@ -35,10 +35,7 @@ pub mod thread { T: Send + 'static, S: Into, { - ::std::thread::Builder::new() - .name(name.into()) - .spawn(f) - .expect("thread spawn works") + ::std::thread::Builder::new().name(name.into()).spawn(f).expect("thread spawn works") } pub use std::thread::*; @@ -87,9 +84,9 @@ pub mod fmt { #[cfg(not(windows))] pub fn start_daemon(program: &str, args: I) -> io::Result<()> - where - I: IntoIterator, - S: AsRef, +where + I: IntoIterator, + S: AsRef, { Command::new(program) .args(args) @@ -109,9 +106,9 @@ pub fn start_daemon(program: &str, args: I) -> io::Result<()> #[cfg(windows)] pub fn start_daemon(program: &str, args: I) -> io::Result<()> - where - I: IntoIterator, - S: AsRef, +where + I: IntoIterator, + S: AsRef, { // Setting all the I/O handles to null and setting the // CREATE_NEW_PROCESS_GROUP and CREATE_NO_WINDOW has the effect diff --git a/src/window.rs b/src/window.rs index 96b62cd..c023197 100644 --- a/src/window.rs +++ b/src/window.rs @@ -15,17 +15,16 @@ use std::convert::From; use std::fmt::Display; use crate::gl; -#[cfg(windows)] -use glutin::Icon; -#[cfg(windows)] -use image::ImageFormat; -use glutin::{ - self, ContextBuilder, ControlFlow, Event, EventsLoop, - MouseCursor, WindowBuilder, ContextTrait -}; use glutin::dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize}; #[cfg(not(any(target_os = "macos", windows)))] use glutin::os::unix::EventsLoopExt; +#[cfg(windows)] +use glutin::Icon; +use glutin::{ + self, ContextBuilder, ContextTrait, ControlFlow, Event, EventsLoop, MouseCursor, WindowBuilder, +}; +#[cfg(windows)] +use image::ImageFormat; use crate::cli::Options; use crate::config::{Decorations, WindowConfig}; @@ -160,12 +159,7 @@ impl Window { // Set OpenGL symbol loader. This call MUST be after window.make_current on windows. gl::load_with(|symbol| window.get_proc_address(symbol) as *const _); - let window = Window { - event_loop, - window, - mouse_visible: true, - is_focused: false, - }; + let window = Window { event_loop, window, mouse_visible: true, is_focused: false }; window.run_os_extensions(); @@ -177,9 +171,7 @@ impl Window { /// Some window properties are provided since subsystems like font /// rasterization depend on DPI and scale factor. pub fn device_properties(&self) -> DeviceProperties { - DeviceProperties { - scale_factor: self.window.get_hidpi_factor(), - } + DeviceProperties { scale_factor: self.window.get_hidpi_factor() } } pub fn inner_size_pixels(&self) -> Option { @@ -204,9 +196,7 @@ impl Window { #[inline] pub fn create_window_proxy(&self) -> Proxy { - Proxy { - inner: self.event_loop.create_proxy(), - } + Proxy { inner: self.event_loop.create_proxy() } } #[inline] @@ -260,7 +250,7 @@ impl Window { pub fn get_platform_window( title: &str, class: &str, - window_config: &WindowConfig + window_config: &WindowConfig, ) -> WindowBuilder { use glutin::os::unix::WindowBuilderExt; @@ -285,7 +275,7 @@ impl Window { pub fn get_platform_window( title: &str, _class: &str, - window_config: &WindowConfig + window_config: &WindowConfig, ) -> WindowBuilder { let icon = Icon::from_bytes_with_format(WINDOW_ICON, ImageFormat::ICO).unwrap(); @@ -307,7 +297,7 @@ impl Window { pub fn get_platform_window( title: &str, _class: &str, - window_config: &WindowConfig + window_config: &WindowConfig, ) -> WindowBuilder { use glutin::os::macos::WindowBuilderExt; @@ -328,19 +318,16 @@ impl Window { .with_titlebar_buttons_hidden(true) .with_titlebar_transparent(true) .with_fullsize_content_view(true), - Decorations::None => window - .with_titlebar_hidden(true), + Decorations::None => window.with_titlebar_hidden(true), } } - #[cfg( - any( - target_os = "linux", - target_os = "freebsd", - target_os = "dragonfly", - target_os = "openbsd" - ) - )] + #[cfg(any( + target_os = "linux", + target_os = "freebsd", + target_os = "dragonfly", + target_os = "openbsd" + ))] pub fn set_urgent(&self, is_urgent: bool) { use glutin::os::unix::WindowExt; self.window.set_urgent(is_urgent); @@ -384,21 +371,20 @@ pub trait OsExtensions { fn run_os_extensions(&self) {} } -#[cfg( - not( - any( - target_os = "linux", - target_os = "freebsd", - target_os = "dragonfly", - target_os = "openbsd" - ) - ) -)] +#[cfg(not(any( + target_os = "linux", + target_os = "freebsd", + target_os = "dragonfly", + target_os = "openbsd" +)))] impl OsExtensions for Window {} -#[cfg( - any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd") -)] +#[cfg(any( + target_os = "linux", + target_os = "freebsd", + target_os = "dragonfly", + target_os = "openbsd" +))] impl OsExtensions for Window { fn run_os_extensions(&self) { use glutin::os::unix::WindowExt; diff --git a/tests/ref.rs b/tests/ref.rs index 75c6e45..4689ac5 100644 --- a/tests/ref.rs +++ b/tests/ref.rs @@ -6,15 +6,15 @@ use std::fs::File; use std::io::{self, Read}; use std::path::Path; -use alacritty::Grid; -use alacritty::Term; use alacritty::ansi; +use alacritty::config::Config; use alacritty::index::Column; +use alacritty::message_bar::MessageBuffer; use alacritty::term::cell::Cell; use alacritty::term::SizeInfo; -use alacritty::util::fmt::{Red, Green}; -use alacritty::config::Config; -use alacritty::message_bar::MessageBuffer; +use alacritty::util::fmt::{Green, Red}; +use alacritty::Grid; +use alacritty::Term; macro_rules! ref_tests { ($($name:ident)*) => { @@ -55,17 +55,18 @@ ref_tests! { } fn read_u8

(path: P) -> Vec - where P: AsRef +where + P: AsRef, { let mut res = Vec::new(); - File::open(path.as_ref()).unwrap() - .read_to_end(&mut res).unwrap(); + File::open(path.as_ref()).unwrap().read_to_end(&mut res).unwrap(); res } fn read_string

(path: P) -> Result - where P: AsRef +where + P: AsRef, { let mut res = String::new(); File::open(path.as_ref()).and_then(|mut f| f.read_to_string(&mut res))?; @@ -109,8 +110,13 @@ fn ref_test(dir: &Path) { let cell = term_grid[i][Column(j)]; let original_cell = grid[i][Column(j)]; if original_cell != cell { - println!("[{i}][{j}] {original:?} => {now:?}", - i=i, j=j, original=Green(original_cell), now=Red(cell)); + println!( + "[{i}][{j}] {original:?} => {now:?}", + i = i, + j = j, + original = Green(original_cell), + now = Red(cell) + ); } } } diff --git a/winpty/build.rs b/winpty/build.rs index 90d8180..0ab379b 100644 --- a/winpty/build.rs +++ b/winpty/build.rs @@ -5,8 +5,10 @@ fn main() { // The working directory for `cargo test` is in the deps folder, not the debug/release root if cfg!(test) && Path::new("target").exists() { #[cfg(debug_assertions)] - copy("../assets/windows/x86_64/winpty-agent.exe", "target/debug/deps/winpty-agent.exe").unwrap(); + copy("../assets/windows/x86_64/winpty-agent.exe", "target/debug/deps/winpty-agent.exe") + .unwrap(); #[cfg(not(debug_assertions))] - copy("../assets/windows/x86_64/winpty-agent.exe", "target/release/deps/winpty-agent.exe").unwrap(); + copy("../assets/windows/x86_64/winpty-agent.exe", "target/release/deps/winpty-agent.exe") + .unwrap(); } } diff --git a/winpty/src/windows.rs b/winpty/src/windows.rs index 03a91a7..064db2d 100644 --- a/winpty/src/windows.rs +++ b/winpty/src/windows.rs @@ -1,9 +1,9 @@ use std::error::Error; use std::fmt::{self, Display, Formatter}; -use std::path::PathBuf; -use std::result::Result; use std::os::windows::io::RawHandle; +use std::path::PathBuf; use std::ptr::{null, null_mut}; +use std::result::Result; use winpty_sys::*; @@ -166,10 +166,7 @@ impl<'a, 'b> Winpty<'a> { pub fn conin_name(&mut self) -> PathBuf { unsafe { let raw = winpty_conin_name(self.0); - PathBuf::from(&String::from_utf16_lossy(std::slice::from_raw_parts( - raw, - wcslen(raw), - ))) + PathBuf::from(&String::from_utf16_lossy(std::slice::from_raw_parts(raw, wcslen(raw)))) } } @@ -178,10 +175,7 @@ impl<'a, 'b> Winpty<'a> { pub fn conout_name(&mut self) -> PathBuf { unsafe { let raw = winpty_conout_name(self.0); - PathBuf::from(&String::from_utf16_lossy(std::slice::from_raw_parts( - raw, - wcslen(raw), - ))) + PathBuf::from(&String::from_utf16_lossy(std::slice::from_raw_parts(raw, wcslen(raw)))) } } @@ -191,10 +185,7 @@ impl<'a, 'b> Winpty<'a> { pub fn conerr_name(&mut self) -> PathBuf { unsafe { let raw = winpty_conerr_name(self.0); - PathBuf::from(&String::from_utf16_lossy(std::slice::from_raw_parts( - raw, - wcslen(raw), - ))) + PathBuf::from(&String::from_utf16_lossy(std::slice::from_raw_parts(raw, wcslen(raw)))) } } @@ -227,7 +218,12 @@ impl<'a, 'b> Winpty<'a> { let mut process_list = Vec::with_capacity(count); unsafe { - let len = winpty_get_console_process_list(self.0, process_list.as_mut_ptr(), count as i32, &mut err) as usize; + let len = winpty_get_console_process_list( + self.0, + process_list.as_mut_ptr(), + count as i32, + &mut err, + ) as usize; process_list.set_len(len); } @@ -246,10 +242,7 @@ impl<'a, 'b> Winpty<'a> { /// (https://blogs.msdn.microsoft.com/oldnewthing/20110107-00/?p=11803) // TODO: Support getting the process and thread handle of the spawned process (Not the agent) // TODO: Support returning the error from CreateProcess - pub fn spawn( - &mut self, - cfg: &SpawnConfig, - ) -> Result<(), Err> { + pub fn spawn(&mut self, cfg: &SpawnConfig) -> Result<(), Err> { let mut err = null_mut() as *mut winpty_error_t; unsafe { @@ -261,7 +254,9 @@ impl<'a, 'b> Winpty<'a> { null_mut(), // Create process error &mut err, ); - if ok == 0 { return Ok(());} + if ok == 0 { + return Ok(()); + } } if let Some(err) = check_err(err) { @@ -354,80 +349,70 @@ mod tests { #[test] // Test that we can start a process in winpty fn spawn_process() { - let mut winpty = Winpty::open( - &Config::new(ConfigFlags::empty()).expect("failed to create config") - ).expect("failed to create winpty instance"); + let mut winpty = + Winpty::open(&Config::new(ConfigFlags::empty()).expect("failed to create config")) + .expect("failed to create winpty instance"); - winpty.spawn( - &SpawnConfig::new( - SpawnFlags::empty(), - None, - Some("cmd"), - None, - None - ).expect("failed to create spawn config") - ).unwrap(); + winpty + .spawn( + &SpawnConfig::new(SpawnFlags::empty(), None, Some("cmd"), None, None) + .expect("failed to create spawn config"), + ) + .unwrap(); } #[test] // Test that pipes connected before winpty is spawned can be connected to fn valid_pipe_connect_before() { - let mut winpty = Winpty::open( - &Config::new(ConfigFlags::empty()).expect("failed to create config") - ).expect("failed to create winpty instance"); + let mut winpty = + Winpty::open(&Config::new(ConfigFlags::empty()).expect("failed to create config")) + .expect("failed to create winpty instance"); // Check we can connect to both pipes - PipeClient::connect_ms(winpty.conout_name(), 1000).expect("failed to connect to conout pipe"); + PipeClient::connect_ms(winpty.conout_name(), 1000) + .expect("failed to connect to conout pipe"); PipeClient::connect_ms(winpty.conin_name(), 1000).expect("failed to connect to conin pipe"); - winpty.spawn( - &SpawnConfig::new( - SpawnFlags::empty(), - None, - Some("cmd"), - None, - None - ).expect("failed to create spawn config") - ).unwrap(); + winpty + .spawn( + &SpawnConfig::new(SpawnFlags::empty(), None, Some("cmd"), None, None) + .expect("failed to create spawn config"), + ) + .unwrap(); } #[test] // Test that pipes connected after winpty is spawned can be connected to fn valid_pipe_connect_after() { - let mut winpty = Winpty::open( - &Config::new(ConfigFlags::empty()).expect("failed to create config") - ).expect("failed to create winpty instance"); + let mut winpty = + Winpty::open(&Config::new(ConfigFlags::empty()).expect("failed to create config")) + .expect("failed to create winpty instance"); - winpty.spawn( - &SpawnConfig::new( - SpawnFlags::empty(), - None, - Some("cmd"), - None, - None - ).expect("failed to create spawn config") - ).unwrap(); + winpty + .spawn( + &SpawnConfig::new(SpawnFlags::empty(), None, Some("cmd"), None, None) + .expect("failed to create spawn config"), + ) + .unwrap(); // Check we can connect to both pipes - PipeClient::connect_ms(winpty.conout_name(), 1000).expect("failed to connect to conout pipe"); + PipeClient::connect_ms(winpty.conout_name(), 1000) + .expect("failed to connect to conout pipe"); PipeClient::connect_ms(winpty.conin_name(), 1000).expect("failed to connect to conin pipe"); } #[test] fn resize() { - let mut winpty = Winpty::open( - &Config::new(ConfigFlags::empty()).expect("failed to create config") - ).expect("failed to create winpty instance"); + let mut winpty = + Winpty::open(&Config::new(ConfigFlags::empty()).expect("failed to create config")) + .expect("failed to create winpty instance"); - winpty.spawn( - &SpawnConfig::new( - SpawnFlags::empty(), - None, - Some("cmd"), - None, - None - ).expect("failed to create spawn config") - ).unwrap(); + winpty + .spawn( + &SpawnConfig::new(SpawnFlags::empty(), None, Some("cmd"), None, None) + .expect("failed to create spawn config"), + ) + .unwrap(); winpty.set_size(1, 1).unwrap(); } @@ -436,21 +421,19 @@ mod tests { #[ignore] // Test that each id returned by cosole_process_list points to an actual process fn console_process_list_valid() { - let mut winpty = Winpty::open( - &Config::new(ConfigFlags::empty()).expect("failed to create config") - ).expect("failed to create winpty instance"); + let mut winpty = + Winpty::open(&Config::new(ConfigFlags::empty()).expect("failed to create config")) + .expect("failed to create winpty instance"); - winpty.spawn( - &SpawnConfig::new( - SpawnFlags::empty(), - None, - Some("cmd"), - None, - None - ).expect("failed to create spawn config") - ).unwrap(); + winpty + .spawn( + &SpawnConfig::new(SpawnFlags::empty(), None, Some("cmd"), None, None) + .expect("failed to create spawn config"), + ) + .unwrap(); - let processes = winpty.console_process_list(1000).expect("failed to get console process list"); + let processes = + winpty.console_process_list(1000).expect("failed to get console process list"); // Check that each id is valid processes.iter().for_each(|id| { @@ -458,7 +441,7 @@ mod tests { OpenProcess( READ_CONTROL, // permissions false as i32, // inheret - *id as u32 + *id as u32, ) }; assert!(!handle.is_null());