mirror of
https://github.com/alacritty/alacritty.git
synced 2024-11-18 13:55:23 -05:00
Before cloning everything
This commit is contained in:
parent
2ede659134
commit
cf886872d0
7 changed files with 182 additions and 48 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -53,6 +53,7 @@ dependencies = [
|
||||||
"serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_yaml 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_yaml 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"smallvec 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"static_assertions 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"static_assertions 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tempfile 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tempfile 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"terminfo 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"terminfo 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|
|
@ -50,6 +50,7 @@ static_assertions = "0.3.0"
|
||||||
terminfo = "0.6.1"
|
terminfo = "0.6.1"
|
||||||
url = "1.7.1"
|
url = "1.7.1"
|
||||||
time = "0.1.40"
|
time = "0.1.40"
|
||||||
|
smallvec = "0.6.6"
|
||||||
|
|
||||||
[target.'cfg(any(target_os = "linux", target_os = "freebsd", target_os="dragonfly", target_os="openbsd"))'.dependencies]
|
[target.'cfg(any(target_os = "linux", target_os = "freebsd", target_os="dragonfly", target_os="openbsd"))'.dependencies]
|
||||||
x11-dl = "2"
|
x11-dl = "2"
|
||||||
|
|
|
@ -758,7 +758,7 @@ impl<'a, T: 'a> DisplayIter<'a, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: Copy + 'a> Iterator for DisplayIter<'a, T> {
|
impl<'a, T: Copy + Clone + 'a> Iterator for DisplayIter<'a, T> {
|
||||||
type Item = Indexed<T>;
|
type Item = Indexed<T>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -65,6 +65,7 @@ extern crate base64;
|
||||||
extern crate terminfo;
|
extern crate terminfo;
|
||||||
extern crate url;
|
extern crate url;
|
||||||
extern crate time;
|
extern crate time;
|
||||||
|
extern crate smallvec;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub mod macros;
|
pub mod macros;
|
||||||
|
|
|
@ -31,7 +31,7 @@ use notify::{watcher, DebouncedEvent, RecursiveMode, Watcher};
|
||||||
use Rgb;
|
use Rgb;
|
||||||
|
|
||||||
use config::{self, Config, Delta};
|
use config::{self, Config, Delta};
|
||||||
use term::{self, cell, RenderableCell};
|
use term::{self, cell, RenderableCell, CellContent};
|
||||||
use glutin::dpi::PhysicalSize;
|
use glutin::dpi::PhysicalSize;
|
||||||
|
|
||||||
// Shader paths for live reload
|
// Shader paths for live reload
|
||||||
|
@ -835,7 +835,7 @@ impl<'a> RenderApi<'a> {
|
||||||
.map(|(i, c)| RenderableCell {
|
.map(|(i, c)| RenderableCell {
|
||||||
line,
|
line,
|
||||||
column: col + i,
|
column: col + i,
|
||||||
c,
|
c: CellContent::SingleChar(c),
|
||||||
bg: color,
|
bg: color,
|
||||||
fg: Rgb { r: 0, g: 0, b: 0 },
|
fg: Rgb { r: 0, g: 0, b: 0 },
|
||||||
flags: cell::Flags::empty(),
|
flags: cell::Flags::empty(),
|
||||||
|
@ -879,35 +879,38 @@ impl<'a> RenderApi<'a> {
|
||||||
glyph_cache.font_key
|
glyph_cache.font_key
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut glyph_key = GlyphKey {
|
// TODO: Skip this iteration if cell is hidden, don't draw underline multiple times
|
||||||
font_key,
|
for character in cell.c.iter() {
|
||||||
size: glyph_cache.font_size,
|
let mut glyph_key = GlyphKey {
|
||||||
c: cell.c,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Don't render text of HIDDEN cells
|
|
||||||
if cell.flags.contains(cell::Flags::HIDDEN) {
|
|
||||||
glyph_key.c = ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add cell to batch
|
|
||||||
{
|
|
||||||
let glyph = glyph_cache.get(glyph_key, self);
|
|
||||||
self.add_render_item(&cell, glyph);
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME This is a super hacky way to do underlined text. During
|
|
||||||
// a time crunch to release 0.1, this seemed like a really
|
|
||||||
// easy, clean hack.
|
|
||||||
if cell.flags.contains(cell::Flags::UNDERLINE) {
|
|
||||||
let glyph_key = GlyphKey {
|
|
||||||
font_key,
|
font_key,
|
||||||
size: glyph_cache.font_size,
|
size: glyph_cache.font_size,
|
||||||
c: '_',
|
c: character,
|
||||||
};
|
};
|
||||||
|
|
||||||
let underscore = glyph_cache.get(glyph_key, self);
|
// Don't render text of HIDDEN cells
|
||||||
self.add_render_item(&cell, underscore);
|
if cell.flags.contains(cell::Flags::HIDDEN) {
|
||||||
|
glyph_key.c = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add cell to batch
|
||||||
|
{
|
||||||
|
let glyph = glyph_cache.get(glyph_key, self);
|
||||||
|
self.add_render_item(&cell, glyph);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME This is a super hacky way to do underlined text. During
|
||||||
|
// a time crunch to release 0.1, this seemed like a really
|
||||||
|
// easy, clean hack.
|
||||||
|
if cell.flags.contains(cell::Flags::UNDERLINE) {
|
||||||
|
let glyph_key = GlyphKey {
|
||||||
|
font_key,
|
||||||
|
size: glyph_cache.font_size,
|
||||||
|
c: '_',
|
||||||
|
};
|
||||||
|
|
||||||
|
let underscore = glyph_cache.get(glyph_key, self);
|
||||||
|
self.add_render_item(&cell, underscore);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
138
src/term/cell.rs
138
src/term/cell.rs
|
@ -11,6 +11,13 @@
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
use smallvec::SmallVec;
|
||||||
|
use serde::de::{SeqAccess, Visitor};
|
||||||
|
use serde::ser::SerializeSeq;
|
||||||
|
use serde::{Serialize, Deserialize, Serializer, Deserializer};
|
||||||
|
|
||||||
use ansi::{NamedColor, Color};
|
use ansi::{NamedColor, Color};
|
||||||
use grid;
|
use grid;
|
||||||
use index::Column;
|
use index::Column;
|
||||||
|
@ -31,9 +38,128 @@ bitflags! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||||
|
pub enum CellContent {
|
||||||
|
SingleChar(char),
|
||||||
|
MultiChar([char; 3]),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CellContent {
|
||||||
|
#[inline]
|
||||||
|
fn is_empty(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
CellContent::SingleChar(c) => c == ' ',
|
||||||
|
CellContent::MultiChar(_) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn primary(&self) -> char {
|
||||||
|
match self {
|
||||||
|
CellContent::SingleChar(c) => *c,
|
||||||
|
CellContent::MultiChar(c) => c[0],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn iter<'a>(&'a self) -> CellContentIter<'a> {
|
||||||
|
CellContentIter::new(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Serialize for CellContent {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
CellContent::SingleChar(c) => serializer.serialize_char(*c),
|
||||||
|
CellContent::MultiChar(c) => {
|
||||||
|
let mut seq = serializer.serialize_seq(Some(c.len()))?;
|
||||||
|
for element in c {
|
||||||
|
seq.serialize_element(&element)?;
|
||||||
|
}
|
||||||
|
seq.end()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for CellContent {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<CellContent, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
struct CellContentVisitor;
|
||||||
|
|
||||||
|
impl<'a> Visitor<'a> for CellContentVisitor {
|
||||||
|
type Value = CellContent;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(formatter, "a char or an array of chars")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_char<E>(self, value: char) -> ::std::result::Result<CellContent, E>
|
||||||
|
where E: ::serde::de::Error
|
||||||
|
{
|
||||||
|
Ok(CellContent::SingleChar(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
||||||
|
where
|
||||||
|
A: SeqAccess<'a>,
|
||||||
|
{
|
||||||
|
let mut array = [' ', 3];
|
||||||
|
let index = 0;
|
||||||
|
while let Some(value) = seq.next_element::<char>()? {
|
||||||
|
array[index] = value;
|
||||||
|
}
|
||||||
|
Ok(CellContent::MultiChar(array))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deserializer.deserialize_any(CellContentVisitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct CellContentIter<'a> {
|
||||||
|
inner: &'a CellContent,
|
||||||
|
index: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> CellContentIter<'a> {
|
||||||
|
fn new(inner: &'a CellContent) -> CellContentIter<'a> {
|
||||||
|
CellContentIter {
|
||||||
|
inner,
|
||||||
|
index: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for CellContentIter<'a> {
|
||||||
|
type Item = char;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<char> {
|
||||||
|
let res = match self.inner {
|
||||||
|
CellContent::SingleChar(c) => if self.index > 0 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(*c)
|
||||||
|
},
|
||||||
|
CellContent::MultiChar(c) => if self.index >= c.len() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(c[self.index])
|
||||||
|
}
|
||||||
|
};
|
||||||
|
self.index += 1;
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
|
||||||
pub struct Cell {
|
pub struct Cell {
|
||||||
pub c: char,
|
pub c: CellContent,
|
||||||
pub fg: Color,
|
pub fg: Color,
|
||||||
pub bg: Color,
|
pub bg: Color,
|
||||||
pub flags: Flags,
|
pub flags: Flags,
|
||||||
|
@ -65,7 +191,7 @@ impl LineLength for grid::Row<Cell> {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (index, cell) in self[..].iter().rev().enumerate() {
|
for (index, cell) in self[..].iter().rev().enumerate() {
|
||||||
if cell.c != ' ' {
|
if !cell.c.is_empty() {
|
||||||
length = Column(self.len() - index);
|
length = Column(self.len() - index);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -93,7 +219,7 @@ impl Cell {
|
||||||
|
|
||||||
pub fn new(c: char, fg: Color, bg: Color) -> Cell {
|
pub fn new(c: char, fg: Color, bg: Color) -> Cell {
|
||||||
Cell {
|
Cell {
|
||||||
c,
|
c: CellContent::SingleChar(c),
|
||||||
bg,
|
bg,
|
||||||
fg,
|
fg,
|
||||||
flags: Flags::empty(),
|
flags: Flags::empty(),
|
||||||
|
@ -102,9 +228,9 @@ impl Cell {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.c == ' ' &&
|
self.c.is_empty()
|
||||||
self.bg == Color::Named(NamedColor::Background) &&
|
&& self.bg == Color::Named(NamedColor::Background)
|
||||||
!self.flags.intersects(Flags::INVERSE | Flags::UNDERLINE)
|
&& !self.flags.intersects(Flags::INVERSE | Flags::UNDERLINE)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -35,7 +35,7 @@ use logging::LoggerProxy;
|
||||||
|
|
||||||
pub mod cell;
|
pub mod cell;
|
||||||
pub mod color;
|
pub mod color;
|
||||||
pub use self::cell::Cell;
|
pub use self::cell::{Cell, CellContent};
|
||||||
use self::cell::LineLength;
|
use self::cell::LineLength;
|
||||||
|
|
||||||
const URL_SEPARATOR_CHARS: [char; 3] = [' ', '"', '\''];
|
const URL_SEPARATOR_CHARS: [char; 3] = [' ', '"', '\''];
|
||||||
|
@ -62,7 +62,7 @@ impl Search for Term {
|
||||||
let last_col = self.grid.num_cols() - Column(1);
|
let last_col = self.grid.num_cols() - Column(1);
|
||||||
|
|
||||||
while let Some(cell) = iter.prev() {
|
while let Some(cell) = iter.prev() {
|
||||||
if self.semantic_escape_chars.contains(cell.c) {
|
if self.semantic_escape_chars.contains(cell.c.primary()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ impl Search for Term {
|
||||||
let last_col = self.grid.num_cols() - Column(1);
|
let last_col = self.grid.num_cols() - Column(1);
|
||||||
|
|
||||||
while let Some(cell) = iter.next() {
|
while let Some(cell) = iter.next() {
|
||||||
if self.semantic_escape_chars.contains(cell.c) {
|
if self.semantic_escape_chars.contains(cell.c.primary()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,16 +112,16 @@ impl Search for Term {
|
||||||
// Put all characters until separators into a string
|
// Put all characters until separators into a string
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
while let Some(cell) = iterb.prev() {
|
while let Some(cell) = iterb.prev() {
|
||||||
if URL_SEPARATOR_CHARS.contains(&cell.c) {
|
if URL_SEPARATOR_CHARS.contains(&cell.c.primary()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
buf.insert(0, cell.c);
|
buf.insert(0, cell.c.primary());
|
||||||
}
|
}
|
||||||
for cell in iterf {
|
for cell in iterf {
|
||||||
if URL_SEPARATOR_CHARS.contains(&cell.c) {
|
if URL_SEPARATOR_CHARS.contains(&cell.c.primary()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
buf.push(cell.c);
|
buf.push(cell.c.primary());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Heuristic to remove all leading '('
|
// Heuristic to remove all leading '('
|
||||||
|
@ -290,7 +290,7 @@ impl<'a> RenderableCellsIter<'a> {
|
||||||
cursor_cell.bg = cursor_color;
|
cursor_cell.bg = cursor_color;
|
||||||
|
|
||||||
let mut wide_cell = cursor_cell;
|
let mut wide_cell = cursor_cell;
|
||||||
wide_cell.c = ' ';
|
wide_cell.c = CellContent::SingleChar(' ');
|
||||||
|
|
||||||
self.push_cursor_cells(original_cell, cursor_cell, wide_cell);
|
self.push_cursor_cells(original_cell, cursor_cell, wide_cell);
|
||||||
}
|
}
|
||||||
|
@ -300,11 +300,11 @@ impl<'a> RenderableCellsIter<'a> {
|
||||||
|
|
||||||
let mut cursor_cell = self.grid[self.cursor];
|
let mut cursor_cell = self.grid[self.cursor];
|
||||||
let cursor_color = self.config.cursor_cursor_color().unwrap_or(cursor_cell.fg);
|
let cursor_color = self.config.cursor_cursor_color().unwrap_or(cursor_cell.fg);
|
||||||
cursor_cell.c = cursor_cell_char;
|
cursor_cell.c = CellContent::SingleChar(cursor_cell_char);
|
||||||
cursor_cell.fg = cursor_color;
|
cursor_cell.fg = cursor_color;
|
||||||
|
|
||||||
let mut wide_cell = cursor_cell;
|
let mut wide_cell = cursor_cell;
|
||||||
wide_cell.c = wide_cell_char;
|
wide_cell.c = CellContent::SingleChar(wide_cell_char);
|
||||||
|
|
||||||
self.push_cursor_cells(original_cell, cursor_cell, wide_cell);
|
self.push_cursor_cells(original_cell, cursor_cell, wide_cell);
|
||||||
}
|
}
|
||||||
|
@ -424,7 +424,7 @@ pub struct RenderableCell {
|
||||||
/// A _Display_ line (not necessarily an _Active_ line)
|
/// A _Display_ line (not necessarily an _Active_ line)
|
||||||
pub line: Line,
|
pub line: Line,
|
||||||
pub column: Column,
|
pub column: Column,
|
||||||
pub c: char,
|
pub c: CellContent,
|
||||||
pub fg: Rgb,
|
pub fg: Rgb,
|
||||||
pub bg: Rgb,
|
pub bg: Rgb,
|
||||||
pub bg_alpha: f32,
|
pub bg_alpha: f32,
|
||||||
|
@ -1029,7 +1029,9 @@ impl Term {
|
||||||
} else if cols.start < line_end {
|
} else if cols.start < line_end {
|
||||||
for cell in &grid_line[cols.start..line_end] {
|
for cell in &grid_line[cols.start..line_end] {
|
||||||
if !cell.flags.contains(cell::Flags::WIDE_CHAR_SPACER) {
|
if !cell.flags.contains(cell::Flags::WIDE_CHAR_SPACER) {
|
||||||
self.push(cell.c);
|
for character in cell.c.iter() {
|
||||||
|
self.push(character);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1386,7 +1388,7 @@ impl ansi::Handler for Term {
|
||||||
|
|
||||||
let cell = &mut self.grid[&self.cursor.point];
|
let cell = &mut self.grid[&self.cursor.point];
|
||||||
*cell = self.cursor.template;
|
*cell = self.cursor.template;
|
||||||
cell.c = self.cursor.charsets[self.active_charset].map(c);
|
cell.c = CellContent::SingleChar(self.cursor.charsets[self.active_charset].map(c));
|
||||||
|
|
||||||
// Handle wide chars
|
// Handle wide chars
|
||||||
if width == 2 {
|
if width == 2 {
|
||||||
|
@ -1416,7 +1418,7 @@ impl ansi::Handler for Term {
|
||||||
fn dectest(&mut self) {
|
fn dectest(&mut self) {
|
||||||
trace!("dectest");
|
trace!("dectest");
|
||||||
let mut template = self.cursor.template;
|
let mut template = self.cursor.template;
|
||||||
template.c = 'E';
|
template.c = CellContent::SingleChar('E');
|
||||||
|
|
||||||
self.grid.region_mut(..)
|
self.grid.region_mut(..)
|
||||||
.each(|c| c.reset(&template));
|
.each(|c| c.reset(&template));
|
||||||
|
|
Loading…
Reference in a new issue