summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock67
-rw-r--r--Cargo.toml3
-rw-r--r--alacritty.yml21
-rw-r--r--src/ansi.rs1
-rw-r--r--src/config.rs300
-rw-r--r--src/macros.rs15
-rw-r--r--src/main.rs66
7 files changed, 434 insertions, 39 deletions
diff --git a/Cargo.lock b/Cargo.lock
index ec79f5fc..269d5191 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -11,6 +11,9 @@ dependencies = [
"libc 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"notify 2.6.1 (git+https://github.com/passcod/rsnotify)",
"parking_lot 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_macros 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_yaml 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -19,6 +22,11 @@ version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "aster"
+version = "0.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
name = "bitflags"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -562,6 +570,27 @@ version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "quasi"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "quasi_codegen"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "aster 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "quasi_macros"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "quasi_codegen 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "rand"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -593,6 +622,39 @@ version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "serde_codegen"
+version = "0.7.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "aster 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quasi 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quasi_macros 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_item 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "serde_item"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "serde_macros"
+version = "0.7.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "serde_codegen 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "serde_yaml"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "serde 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "yaml-rust 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "servo-fontconfig"
version = "0.2.0"
source = "git+https://github.com/jwilm/rust-fontconfig#419135e5e1106ec0973dd4923bd9c70d8e438cc8"
@@ -767,3 +829,8 @@ dependencies = [
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
+[[package]]
+name = "yaml-rust"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
diff --git a/Cargo.toml b/Cargo.toml
index d069daf9..22db5f00 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -14,6 +14,9 @@ bitflags = "*"
font = { path = "./font" }
errno = "0.1.6"
parking_lot = "0.2.6"
+serde = "0.7"
+serde_yaml = "0.2"
+serde_macros = "0.7"
[build-dependencies]
gl_generator = "0.5"
diff --git a/alacritty.yml b/alacritty.yml
new file mode 100644
index 00000000..e0d1d3fa
--- /dev/null
+++ b/alacritty.yml
@@ -0,0 +1,21 @@
+# Configuration for Alacritty, the GPU enhanced terminal emulator
+
+# The FreeType rasterizer needs to know the device DPI for best results
+dpi:
+ x: 96.0
+ y: 96.0
+
+# Font configuration
+font:
+ family: DejaVu Sans Mono
+ style: Book
+ # Point size of the font
+ size: 11.0
+ # Offset is the extra space around each character. offset.y can be thought of
+ # as modifying the linespacing, and offset.x as modifying the letter spacing.
+ offset:
+ x: 2.0
+ y: -7.0
+
+# Should display the render timer
+render_timer: false
diff --git a/src/ansi.rs b/src/ansi.rs
index 2fc3e4f3..5d4d9e4c 100644
--- a/src/ansi.rs
+++ b/src/ansi.rs
@@ -31,7 +31,6 @@
//! should be, feel free to add it. Please try not to become overzealous and adding support for
//! sequences only used by folks trapped in 1988.
-use std::io::Write;
use ::Rgb;
/// A CSI Escape sequence
diff --git a/src/config.rs b/src/config.rs
new file mode 100644
index 00000000..426a3381
--- /dev/null
+++ b/src/config.rs
@@ -0,0 +1,300 @@
+//! Configuration definitions and file loading
+//!
+//! Alacritty reads from a config file at startup to determine various runtime
+//! 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::env;
+use std::fs;
+use std::io::{self, Read};
+use std::path::{Path, PathBuf};
+
+use serde_yaml;
+
+/// Top-level config type
+#[derive(Debug, Deserialize, Default)]
+pub struct Config {
+ /// Pixels per inch
+ #[serde(default)]
+ dpi: Dpi,
+
+ /// Font configuration
+ #[serde(default)]
+ font: Font,
+
+ /// Should show render timer
+ #[serde(default)]
+ render_timer: bool,
+}
+
+/// Errors occurring during config loading
+#[derive(Debug)]
+pub enum Error {
+ /// Config file not found
+ NotFound,
+
+ /// Couldn't read $HOME environment variable
+ ReadingEnvHome(env::VarError),
+
+ /// io error reading file
+ Io(io::Error),
+
+ /// Not valid yaml or missing parameters
+ Yaml(serde_yaml::Error),
+}
+
+impl ::std::error::Error for Error {
+ fn cause(&self) -> Option<&::std::error::Error> {
+ match *self {
+ Error::NotFound => None,
+ Error::ReadingEnvHome(ref err) => Some(err),
+ Error::Io(ref err) => Some(err),
+ Error::Yaml(ref err) => Some(err),
+ }
+ }
+
+ fn description(&self) -> &str {
+ match *self {
+ Error::NotFound => "could not locate config file",
+ Error::ReadingEnvHome(ref err) => err.description(),
+ Error::Io(ref err) => err.description(),
+ Error::Yaml(ref err) => err.description(),
+ }
+ }
+}
+
+impl ::std::fmt::Display for Error {
+ fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
+ match *self {
+ Error::NotFound => write!(f, "{}", ::std::error::Error::description(self)),
+ Error::ReadingEnvHome(ref err) => {
+ write!(f, "could not read $HOME environment variable: {}", err)
+ },
+ Error::Io(ref err) => write!(f, "error reading config file: {}", err),
+ Error::Yaml(ref err) => write!(f, "problem with config: {}", err),
+ }
+ }
+}
+
+impl From<env::VarError> for Error {
+ fn from(val: env::VarError) -> Error {
+ Error::ReadingEnvHome(val)
+ }
+}
+
+impl From<io::Error> for Error {
+ fn from(val: io::Error) -> Error {
+ if val.kind() == io::ErrorKind::NotFound {
+ Error::NotFound
+ } else {
+ Error::Io(val)
+ }
+ }
+}
+
+impl From<serde_yaml::Error> for Error {
+ fn from(val: serde_yaml::Error) -> Error {
+ Error::Yaml(val)
+ }
+}
+
+/// Result from config loading
+pub type Result<T> = ::std::result::Result<T, Error>;
+
+impl Config {
+ /// Attempt to load the config file
+ ///
+ /// The config file is loaded from the first file it finds in this list of paths
+ ///
+ /// 1. `$HOME/.config/alacritty.yml`
+ /// 2. `$HOME/.alacritty.yml`
+ pub fn load() -> Result<Config> {
+ let home = env::var("HOME")?;
+
+ // First path
+ let mut path = PathBuf::from(&home);
+ path.push(".config");
+ path.push("alacritty.yml");
+
+ // Fallback path
+ let mut alt_path = PathBuf::from(&home);
+ alt_path.push(".alacritty.yml");
+
+ match Config::load_from(&path) {
+ Ok(c) => Ok(c),
+ Err(e) => {
+ match e {
+ Error::NotFound => Config::load_from(&alt_path),
+ _ => Err(e),
+ }
+ }
+ }
+ }
+
+ /// Get font config
+ #[inline]
+ pub fn font(&self) -> &Font {
+ &self.font
+ }
+
+ /// Get dpi config
+ #[inline]
+ pub fn dpi(&self) -> &Dpi {
+ &self.dpi
+ }
+
+ /// Should show render timer
+ #[inline]
+ pub fn render_timer(&self) -> bool {
+ self.render_timer
+ }
+
+ fn load_from<P: AsRef<Path>>(path: P) -> Result<Config> {
+ let raw = Config::read_file(path)?;
+ Ok(serde_yaml::from_str(&raw[..])?)
+ }
+
+ fn read_file<P: AsRef<Path>>(path: P) -> Result<String> {
+ let mut f = fs::File::open(path)?;
+ let mut contents = String::new();
+ f.read_to_string(&mut contents)?;
+
+ Ok(contents)
+ }
+}
+
+/// Pixels per inch
+///
+/// This is only used on FreeType systems
+#[derive(Debug, Deserialize)]
+pub struct Dpi {
+ /// Horizontal dpi
+ x: f32,
+
+ /// Vertical dpi
+ y: f32,
+}
+
+impl Default for Dpi {
+ fn default() -> Dpi {
+ Dpi { x: 96.0, y: 96.0 }
+ }
+}
+
+impl Dpi {
+ /// Get horizontal dpi
+ #[inline]
+ pub fn x(&self) -> f32 {
+ self.x
+ }
+
+ /// Get vertical dpi
+ #[inline]
+ pub fn y(&self) -> f32 {
+ self.y
+ }
+}
+
+/// Modifications to font spacing
+///
+/// The way Alacritty calculates vertical and horizontal cell sizes may not be
+/// ideal for all fonts. This gives the user a way to tweak those values.
+#[derive(Debug, Deserialize)]
+pub struct FontOffset {
+ /// Extra horizontal spacing between letters
+ x: f32,
+ /// Extra vertical spacing between lines
+ y: f32,
+}
+
+impl FontOffset {
+ /// Get letter spacing
+ #[inline]
+ pub fn x(&self) -> f32 {
+ self.x
+ }
+
+ /// Get line spacing
+ #[inline]
+ pub fn y(&self) -> f32 {
+ self.y
+ }
+}
+
+/// Font config
+///
+/// Defaults are provided at the level of this struct per platform, but not per
+/// field in this struct. It might be nice in the future to have defaults for
+/// each value independently. Alternatively, maybe erroring when the user
+/// doesn't provide complete config is Ok.
+#[derive(Debug, Deserialize)]
+pub struct Font {
+ /// Font family
+ family: String,
+
+ /// Font style
+ style: String,
+
+ /// Font size in points
+ size: f32,
+
+ /// Extra spacing per character
+ offset: FontOffset,
+}
+
+impl Font {
+ /// Get the font family
+ #[inline]
+ pub fn family(&self) -> &str {
+ &self.family[..]
+ }
+
+ /// Get the font style
+ #[inline]
+ pub fn style(&self) -> &str {
+ &self.style[..]
+ }
+
+ /// Get the font size in points
+ #[inline]
+ pub fn size(&self) -> f32 {
+ self.size
+ }
+
+ /// Get offsets to font metrics
+ #[inline]
+ pub fn offset(&self) -> &FontOffset {
+ &self.offset
+ }
+}
+
+#[cfg(target_os = "macos")]
+impl Default for Font {
+ fn default() -> Font {
+ Font {
+ family: String::from("Menlo"),
+ style: String::from("Regular"),
+ size: 11.0,
+ offset: FontOffset {
+ x: 0.0,
+ y: 0.0
+ }
+ }
+ }
+}
+
+#[cfg(target_os = "linux")]
+impl Default for Font {
+ fn default() -> Font {
+ Font {
+ family: String::from("DejaVu Sans Mono"),
+ style: String::from("Book"),
+ size: 11.0,
+ offset: FontOffset {
+ // TODO should improve freetype metrics... shouldn't need such
+ // drastic offsets for the default!
+ x: 2.0,
+ y: -7.0
+ }
+ }
+ }
+}
diff --git a/src/macros.rs b/src/macros.rs
index e35eeb90..8abad78d 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -14,17 +14,16 @@
#[macro_export]
macro_rules! die {
- ($($arg:tt)*) => {
- println!($($arg)*);
+ ($($arg:tt)*) => {{
+ err_println!($($arg)*);
::std::process::exit(1);
- }
+ }}
}
#[macro_export]
macro_rules! err_println {
- ($($arg:tt)*) => {
- if let Err(_) = writeln!(&mut ::std::io::stderr(), $($arg)*) {
- die!("Cannot reach stderr");
- }
- }
+ ($($arg:tt)*) => {{
+ use std::io::Write;
+ (writeln!(&mut ::std::io::stderr(), $($arg)*)).expect("stderr");
+ }}
}
diff --git a/src/main.rs b/src/main.rs
index ec68ebf6..b699fe44 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -19,14 +19,18 @@
#![feature(io)]
#![feature(drop_types_in_const)]
#![feature(unicode)]
+#![feature(custom_derive, plugin)]
+#![plugin(serde_macros)]
+extern crate cgmath;
+extern crate errno;
extern crate font;
-extern crate libc;
extern crate glutin;
-extern crate cgmath;
+extern crate libc;
extern crate notify;
-extern crate errno;
extern crate parking_lot;
+extern crate serde;
+extern crate serde_yaml;
#[macro_use]
extern crate bitflags;
@@ -37,6 +41,7 @@ mod macros;
mod renderer;
pub mod grid;
mod meter;
+pub mod config;
mod input;
mod tty;
pub mod ansi;
@@ -49,6 +54,7 @@ use std::sync::{mpsc, Arc};
use parking_lot::Mutex;
+use config::Config;
use font::FontDesc;
use meter::Meter;
use renderer::{QuadRenderer, GlyphCache};
@@ -131,18 +137,21 @@ mod gl {
include!(concat!(env!("OUT_DIR"), "/gl_bindings.rs"));
}
-#[cfg(target_os = "linux")]
-static FONT: &'static str = "DejaVu Sans Mono";
-#[cfg(target_os = "linux")]
-static FONT_STYLE: &'static str = "Book";
-
-#[cfg(target_os = "macos")]
-static FONT: &'static str = "Menlo";
-#[cfg(target_os = "macos")]
-static FONT_STYLE: &'static str = "Regular";
-
-
fn main() {
+ // Load configuration
+ let config = match Config::load() {
+ Err(err) => match err {
+ // Use default config when not found
+ config::Error::NotFound => Config::default(),
+ // Exit when there's a problem with it
+ _ => die!("{}", err),
+ },
+ Ok(config) => config,
+ };
+
+ let font = config.font();
+ let dpi = config.dpi();
+ let render_timer = config.render_timer();
let mut window = glutin::WindowBuilder::new()
.with_vsync()
@@ -156,17 +165,12 @@ fn main() {
println!("device_pixel_ratio: {}", dpr);
- let font_size = 11.;
-
- let sep_x = 0.0;
- let sep_y = 0.0;
+ let desc = FontDesc::new(font.family(), font.style());
+ let mut rasterizer = font::Rasterizer::new(dpi.x(), dpi.y(), dpr);
- let desc = FontDesc::new(FONT, FONT_STYLE);
- let mut rasterizer = font::Rasterizer::new(96., 96., dpr);
-
- let metrics = rasterizer.metrics(&desc, font_size);
- let cell_width = (metrics.average_advance + sep_x) as u32;
- let cell_height = (metrics.line_height + sep_y) as u32;
+ let metrics = rasterizer.metrics(&desc, font.size());
+ let cell_width = (metrics.average_advance + font.offset().x() as f64) as u32;
+ let cell_height = (metrics.line_height + font.offset().y() as f64) as u32;
println!("Cell Size: ({} x {})", cell_width, cell_height);
@@ -175,7 +179,7 @@ fn main() {
let reader = terminal.tty().reader();
let writer = terminal.tty().writer();
- let mut glyph_cache = GlyphCache::new(rasterizer, desc, font_size);
+ let mut glyph_cache = GlyphCache::new(rasterizer, desc, font.size());
let needs_render = Arc::new(AtomicBool::new(true));
let needs_render2 = needs_render.clone();
@@ -322,11 +326,13 @@ fn main() {
}
// Draw render timer
- let timing = format!("{:.3} usec", meter.average());
- let color = Rgb { r: 0xd5, g: 0x4e, b: 0x53 };
- renderer.with_api(terminal.size_info(), |mut api| {
- api.render_string(&timing[..], &mut glyph_cache, &color);
- });
+ if render_timer {
+ let timing = format!("{:.3} usec", meter.average());
+ let color = Rgb { r: 0xd5, g: 0x4e, b: 0x53 };
+ renderer.with_api(terminal.size_info(), |mut api| {
+ api.render_string(&timing[..], &mut glyph_cache, &color);
+ });
+ }
}
window.swap_buffers().unwrap();