mirror of
https://github.com/alacritty/alacritty.git
synced 2024-11-03 04:34:21 -05:00
Add support for wide characters
This commit is contained in:
parent
55876522a2
commit
119c7d2856
5 changed files with 87 additions and 32 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -22,6 +22,7 @@ dependencies = [
|
||||||
"serde_derive 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_derive 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_json 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_yaml 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_yaml 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"vte 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"vte 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"xdg 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"xdg 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
|
@ -31,6 +31,7 @@ xdg = "2.0.0"
|
||||||
log = "0.3"
|
log = "0.3"
|
||||||
clap = "2.20"
|
clap = "2.20"
|
||||||
fnv = "1.0.5"
|
fnv = "1.0.5"
|
||||||
|
unicode-width = "0.1.4"
|
||||||
|
|
||||||
clippy = { version = "0.0.104", optional = true }
|
clippy = { version = "0.0.104", optional = true }
|
||||||
|
|
||||||
|
|
20
src/lib.rs
20
src/lib.rs
|
@ -21,19 +21,18 @@
|
||||||
#![cfg_attr(feature = "clippy", deny(wrong_pub_self_convention))]
|
#![cfg_attr(feature = "clippy", deny(wrong_pub_self_convention))]
|
||||||
#![cfg_attr(feature = "nightly", feature(core_intrinsics))]
|
#![cfg_attr(feature = "nightly", feature(core_intrinsics))]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use] extern crate bitflags;
|
||||||
extern crate serde_derive;
|
#[macro_use] extern crate clap;
|
||||||
|
#[macro_use] extern crate lazy_static;
|
||||||
|
#[macro_use] extern crate log;
|
||||||
|
#[macro_use] extern crate serde_derive;
|
||||||
|
|
||||||
extern crate cgmath;
|
extern crate cgmath;
|
||||||
#[macro_use]
|
|
||||||
extern crate clap;
|
|
||||||
extern crate copypasta;
|
extern crate copypasta;
|
||||||
extern crate errno;
|
extern crate errno;
|
||||||
extern crate font;
|
|
||||||
extern crate fnv;
|
extern crate fnv;
|
||||||
|
extern crate font;
|
||||||
extern crate glutin;
|
extern crate glutin;
|
||||||
#[macro_use]
|
|
||||||
extern crate lazy_static;
|
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
extern crate mio;
|
extern crate mio;
|
||||||
extern crate notify;
|
extern crate notify;
|
||||||
|
@ -41,15 +40,10 @@ extern crate parking_lot;
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
extern crate serde_yaml;
|
extern crate serde_yaml;
|
||||||
|
extern crate unicode_width;
|
||||||
extern crate vte;
|
extern crate vte;
|
||||||
extern crate xdg;
|
extern crate xdg;
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate bitflags;
|
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate log;
|
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub mod macros;
|
pub mod macros;
|
||||||
|
|
||||||
|
|
|
@ -18,11 +18,13 @@ use index::Column;
|
||||||
bitflags! {
|
bitflags! {
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub flags Flags: u32 {
|
pub flags Flags: u32 {
|
||||||
const INVERSE = 0b00000001,
|
const INVERSE = 0b00000001,
|
||||||
const BOLD = 0b00000010,
|
const BOLD = 0b00000010,
|
||||||
const ITALIC = 0b00000100,
|
const ITALIC = 0b00000100,
|
||||||
const UNDERLINE = 0b00001000,
|
const UNDERLINE = 0b00001000,
|
||||||
const WRAPLINE = 0b00010000,
|
const WRAPLINE = 0b00010000,
|
||||||
|
const WIDE_CHAR = 0b00100000,
|
||||||
|
const WIDE_CHAR_SPACER = 0b01000000,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,8 @@ use std::cmp::min;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
|
use unicode_width::UnicodeWidthChar;
|
||||||
|
|
||||||
use ansi::{self, Color, NamedColor, Attr, Handler, CharsetIndex, StandardCharset};
|
use ansi::{self, Color, NamedColor, Attr, Handler, CharsetIndex, StandardCharset};
|
||||||
use grid::{BidirectionalIterator, Grid, ClearRegion, ToRange, Indexed};
|
use grid::{BidirectionalIterator, Grid, ClearRegion, ToRange, Indexed};
|
||||||
use index::{self, Point, Column, Line, Linear, IndexRange, Contains, RangeInclusive, Side};
|
use index::{self, Point, Column, Line, Linear, IndexRange, Contains, RangeInclusive, Side};
|
||||||
|
@ -49,7 +51,7 @@ pub struct RenderableCellsIter<'a> {
|
||||||
config: &'a Config,
|
config: &'a Config,
|
||||||
colors: &'a color::List,
|
colors: &'a color::List,
|
||||||
selection: Option<RangeInclusive<index::Linear>>,
|
selection: Option<RangeInclusive<index::Linear>>,
|
||||||
cursor_original: Option<Indexed<Cell>>
|
cursor_original: (Option<Indexed<Cell>>, Option<Indexed<Cell>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> RenderableCellsIter<'a> {
|
impl<'a> RenderableCellsIter<'a> {
|
||||||
|
@ -77,25 +79,52 @@ impl<'a> RenderableCellsIter<'a> {
|
||||||
selection: selection,
|
selection: selection,
|
||||||
config: config,
|
config: config,
|
||||||
colors: colors,
|
colors: colors,
|
||||||
cursor_original: None,
|
cursor_original: (None, None),
|
||||||
}.initialize()
|
}.initialize()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initialize(mut self) -> Self {
|
fn initialize(mut self) -> Self {
|
||||||
if self.cursor_is_visible() {
|
if self.cursor_is_visible() {
|
||||||
self.cursor_original = Some(Indexed {
|
self.cursor_original.0 = Some(Indexed {
|
||||||
line: self.cursor.line,
|
line: self.cursor.line,
|
||||||
column: self.cursor.col,
|
column: self.cursor.col,
|
||||||
inner: self.grid[self.cursor]
|
inner: self.grid[self.cursor]
|
||||||
});
|
});
|
||||||
|
let mut spacer = false;
|
||||||
|
let mut location = *self.cursor;
|
||||||
|
|
||||||
|
if self.grid[self.cursor].flags.contains(cell::WIDE_CHAR) &&
|
||||||
|
self.cursor.col + 1 < self.grid.num_cols()
|
||||||
|
{
|
||||||
|
spacer = true;
|
||||||
|
location.col += 1;
|
||||||
|
self.cursor_original.1 = Some(Indexed {
|
||||||
|
line: location.line,
|
||||||
|
column: location.col,
|
||||||
|
inner: self.grid[&location]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if self.config.custom_cursor_colors() {
|
if self.config.custom_cursor_colors() {
|
||||||
let cell = &mut self.grid[self.cursor];
|
{
|
||||||
cell.fg = Color::Named(NamedColor::CursorText);
|
let cell = &mut self.grid[self.cursor];
|
||||||
cell.bg = Color::Named(NamedColor::Cursor);
|
cell.fg = Color::Named(NamedColor::CursorText);
|
||||||
|
cell.bg = Color::Named(NamedColor::Cursor);
|
||||||
|
}
|
||||||
|
if spacer {
|
||||||
|
let cell = &mut self.grid[&location];
|
||||||
|
cell.fg = Color::Named(NamedColor::CursorText);
|
||||||
|
cell.bg = Color::Named(NamedColor::Cursor);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
let cell = &mut self.grid[self.cursor];
|
{
|
||||||
mem::swap(&mut cell.fg, &mut cell.bg);
|
let cell = &mut self.grid[self.cursor];
|
||||||
|
mem::swap(&mut cell.fg, &mut cell.bg);
|
||||||
|
}
|
||||||
|
if spacer {
|
||||||
|
let cell = &mut self.grid[&location];
|
||||||
|
mem::swap(&mut cell.fg, &mut cell.bg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
|
@ -112,9 +141,14 @@ impl<'a> Drop for RenderableCellsIter<'a> {
|
||||||
/// Resets temporary render state on the grid
|
/// Resets temporary render state on the grid
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if self.cursor_is_visible() {
|
if self.cursor_is_visible() {
|
||||||
if let Some(ref original) = self.cursor_original {
|
if let Some(ref original) = self.cursor_original.0 {
|
||||||
self.grid[self.cursor] = original.inner;
|
self.grid[self.cursor] = original.inner;
|
||||||
}
|
}
|
||||||
|
if let Some(ref original) = self.cursor_original.1 {
|
||||||
|
let mut location = *self.cursor;
|
||||||
|
location.col += 1;
|
||||||
|
self.grid[&location] = original.inner;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -702,7 +736,9 @@ impl Term {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
for cell in &line[cols.start..line_end] {
|
for cell in &line[cols.start..line_end] {
|
||||||
self.push(cell.c);
|
if !cell.flags.contains(cell::WIDE_CHAR_SPACER) {
|
||||||
|
self.push(cell.c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(cols.start..line_end)
|
Some(cols.start..line_end)
|
||||||
|
@ -1001,7 +1037,6 @@ impl ansi::Handler for Term {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn input(&mut self, c: char) {
|
fn input(&mut self, c: char) {
|
||||||
if self.input_needs_wrap {
|
if self.input_needs_wrap {
|
||||||
|
|
||||||
if !self.mode.contains(mode::LINE_WRAP) {
|
if !self.mode.contains(mode::LINE_WRAP) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1029,9 +1064,31 @@ impl ansi::Handler for Term {
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let cell = &mut self.grid[&self.cursor.point];
|
// Number of cells the char will occupy
|
||||||
*cell = self.cursor.template;
|
let width = c.width();
|
||||||
cell.c = self.cursor.charsets[self.active_charset].map(c);
|
|
||||||
|
// Sigh, borrowck making us check the width twice. Hopefully the
|
||||||
|
// optimizer can fix it.
|
||||||
|
{
|
||||||
|
let cell = &mut self.grid[&self.cursor.point];
|
||||||
|
*cell = self.cursor.template;
|
||||||
|
cell.c = self.cursor.charsets[self.active_charset].map(c);
|
||||||
|
|
||||||
|
// Handle wide chars
|
||||||
|
if let Some(2) = width {
|
||||||
|
cell.flags.insert(cell::WIDE_CHAR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set spacer cell for wide chars.
|
||||||
|
if let Some(2) = width {
|
||||||
|
if self.cursor.point.col + 1 < self.grid.num_cols() {
|
||||||
|
self.cursor.point.col += 1;
|
||||||
|
let spacer = &mut self.grid[&self.cursor.point];
|
||||||
|
*spacer = self.cursor.template;
|
||||||
|
spacer.flags.insert(cell::WIDE_CHAR_SPACER);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.cursor.point.col + 1) < self.grid.num_cols() {
|
if (self.cursor.point.col + 1) < self.grid.num_cols() {
|
||||||
|
|
Loading…
Reference in a new issue