diff options
| author | Theodore Dubois <tblodt@icloud.com> | 2019-04-28 06:24:58 -0700 |
|---|---|---|
| committer | Christian Duerr <chrisduerr@users.noreply.github.com> | 2019-04-28 13:24:58 +0000 |
| commit | dbd8538762ef8968a493e1bf996e8693479ca783 (patch) | |
| tree | 32ac2a6a5e01238a272d4ba534551d2e42903c7a /src | |
| parent | 9c6d12ea2c863ba76015bdedc00db13b7307725a (diff) | |
| download | r-alacritty-dbd8538762ef8968a493e1bf996e8693479ca783.tar.gz r-alacritty-dbd8538762ef8968a493e1bf996e8693479ca783.tar.bz2 r-alacritty-dbd8538762ef8968a493e1bf996e8693479ca783.zip | |
Split alacritty into a separate crates
The crate containing the entry point is called alacritty, and the crate
containing everything else is called alacritty_terminal.
Diffstat (limited to 'src')
37 files changed, 0 insertions, 19304 deletions
diff --git a/src/ansi.rs b/src/ansi.rs deleted file mode 100644 index c0ebb79c..00000000 --- a/src/ansi.rs +++ /dev/null @@ -1,1568 +0,0 @@ -// Copyright 2016 Joe Wilm, The Alacritty Project Contributors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// 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. -// -//! ANSI Terminal Stream Parsing -use std::io; -use std::ops::Range; -use std::str; - -use crate::index::{Column, Contains, Line}; -use base64; -use glutin::MouseCursor; -use vte; - -use crate::term::color::Rgb; - -// Parse color arguments -// -// Expect that color argument looks like "rgb:xx/xx/xx" or "#xxxxxx" -fn parse_rgb_color(color: &[u8]) -> Option<Rgb> { - let mut iter = color.iter(); - - macro_rules! next { - () => { - iter.next().map(|v| *v as char) - }; - } - - macro_rules! parse_hex { - () => {{ - let mut digit: u8 = 0; - let next = next!().and_then(|v| v.to_digit(16)); - if let Some(value) = next { - digit = value as u8; - } - - let next = next!().and_then(|v| v.to_digit(16)); - if let Some(value) = next { - digit <<= 4; - 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; - } - - let r = parse_hex!(); - let val = next!(); - if val != Some('/') { - return None; - } - let g = parse_hex!(); - 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, - } -} - -fn parse_number(input: &[u8]) -> Option<u8> { - if input.is_empty() { - return None; - } - let mut num: u8 = 0; - for c in input { - let c = *c as char; - if let Some(digit) = c.to_digit(10) { - num = match num.checked_mul(10).and_then(|v| v.checked_add(digit as u8)) { - Some(v) => v, - None => return None, - } - } else { - return None; - } - } - Some(num) -} - -/// The processor wraps a `vte::Parser` to ultimately call methods on a Handler -pub struct Processor { - state: ProcessorState, - parser: vte::Parser, -} - -/// Internal state for VTE processor -struct ProcessorState { - preceding_char: Option<char>, -} - -/// Helper type that implements `vte::Perform`. -/// -/// Processor creates a Performer when running advance and passes the Performer -/// to `vte::Parser`. -struct Performer<'a, H: Handler + TermInfo, W: io::Write> { - _state: &'a mut ProcessorState, - handler: &'a mut H, - writer: &'a mut W, -} - -impl<'a, H: Handler + TermInfo + 'a, W: io::Write> Performer<'a, H, W> { - /// Create a performer - #[inline] - pub fn new<'b>( - state: &'b mut ProcessorState, - handler: &'b mut H, - writer: &'b mut W, - ) -> Performer<'b, H, W> { - Performer { _state: state, handler, writer } - } -} - -impl Default for Processor { - fn default() -> Processor { - Processor { state: ProcessorState { preceding_char: None }, parser: vte::Parser::new() } - } -} - -impl Processor { - pub fn new() -> Processor { - Default::default() - } - - #[inline] - pub fn advance<H, W>(&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; - fn cols(&self) -> Column; -} - -/// Type that handles actions from the parser -/// -/// XXX Should probably not provide default impls for everything, but it makes -/// writing specific handler impls for tests far easier. -pub trait Handler { - /// OSC to set window title - fn set_title(&mut self, _: &str) {} - - /// Set the window's mouse cursor - fn set_mouse_cursor(&mut self, _: MouseCursor) {} - - /// Set the cursor style - fn set_cursor_style(&mut self, _: Option<CursorStyle>) {} - - /// A character to be displayed - fn input(&mut self, _c: char) {} - - /// Set cursor to position - fn goto(&mut self, _: Line, _: Column) {} - - /// Set cursor to specific row - fn goto_line(&mut self, _: Line) {} - - /// Set cursor to specific column - fn goto_col(&mut self, _: Column) {} - - /// Insert blank characters in current line starting from cursor - fn insert_blank(&mut self, _: Column) {} - - /// Move cursor up `rows` - fn move_up(&mut self, _: Line) {} - - /// Move cursor down `rows` - fn move_down(&mut self, _: Line) {} - - /// Identify the terminal (should write back to the pty stream) - /// - /// TODO this should probably return an io::Result - fn identify_terminal<W: io::Write>(&mut self, _: &mut W) {} - - // Report device status - fn device_status<W: io::Write>(&mut self, _: &mut W, _: usize) {} - - /// Move cursor forward `cols` - fn move_forward(&mut self, _: Column) {} - - /// Move cursor backward `cols` - fn move_backward(&mut self, _: Column) {} - - /// Move cursor down `rows` and set to column 1 - fn move_down_and_cr(&mut self, _: Line) {} - - /// Move cursor up `rows` and set to column 1 - fn move_up_and_cr(&mut self, _: Line) {} - - /// Put `count` tabs - fn put_tab(&mut self, _count: i64) {} - - /// Backspace `count` characters - fn backspace(&mut self) {} - - /// Carriage return - fn carriage_return(&mut self) {} - - /// Linefeed - fn linefeed(&mut self) {} - - /// Ring the bell - /// - /// Hopefully this is never implemented - fn bell(&mut self) {} - - /// Substitute char under cursor - fn substitute(&mut self) {} - - /// Newline - fn newline(&mut self) {} - - /// Set current position as a tabstop - fn set_horizontal_tabstop(&mut self) {} - - /// Scroll up `rows` rows - fn scroll_up(&mut self, _: Line) {} - - /// Scroll down `rows` rows - fn scroll_down(&mut self, _: Line) {} - - /// Insert `count` blank lines - fn insert_blank_lines(&mut self, _: Line) {} - - /// Delete `count` lines - fn delete_lines(&mut self, _: Line) {} - - /// Erase `count` chars in current line following cursor - /// - /// Erase means resetting to the default state (default colors, no content, - /// no mode flags) - fn erase_chars(&mut self, _: Column) {} - - /// Delete `count` chars - /// - /// Deleting a character is like the delete key on the keyboard - everything - /// to the right of the deleted things is shifted left. - fn delete_chars(&mut self, _: Column) {} - - /// Move backward `count` tabs - fn move_backward_tabs(&mut self, _count: i64) {} - - /// Move forward `count` tabs - fn move_forward_tabs(&mut self, _count: i64) {} - - /// Save current cursor position - fn save_cursor_position(&mut self) {} - - /// Restore cursor position - fn restore_cursor_position(&mut self) {} - - /// Clear current line - fn clear_line(&mut self, _mode: LineClearMode) {} - - /// Clear screen - fn clear_screen(&mut self, _mode: ClearMode) {} - - /// Clear tab stops - fn clear_tabs(&mut self, _mode: TabulationClearMode) {} - - /// Reset terminal state - fn reset_state(&mut self) {} - - /// Reverse Index - /// - /// Move the active position to the same horizontal position on the - /// preceding line. If the active position is at the top margin, a scroll - /// down is performed - fn reverse_index(&mut self) {} - - /// set a terminal attribute - fn terminal_attribute(&mut self, _attr: Attr) {} - - /// Set mode - fn set_mode(&mut self, _mode: Mode) {} - - /// Unset mode - fn unset_mode(&mut self, _: Mode) {} - - /// DECSTBM - Set the terminal scrolling region - fn set_scrolling_region(&mut self, _: Range<Line>) {} - - /// DECKPAM - Set keypad to applications mode (ESCape instead of digits) - fn set_keypad_application_mode(&mut self) {} - - /// DECKPNM - Set keypad to numeric mode (digits instead of ESCape seq) - fn unset_keypad_application_mode(&mut self) {} - - /// Set one of the graphic character sets, G0 to G3, as the active charset. - /// - /// 'Invoke' one of G0 to G3 in the GL area. Also referred to as shift in, - /// shift out and locking shift depending on the set being activated - fn set_active_charset(&mut self, _: CharsetIndex) {} - - /// Assign a graphic character set to G0, G1, G2 or G3 - /// - /// 'Designate' a graphic character set as one of G0 to G3, so that it can - /// later be 'invoked' by `set_active_charset` - fn configure_charset(&mut self, _: CharsetIndex, _: StandardCharset) {} - - /// Set an indexed color value - fn set_color(&mut self, _: usize, _: Rgb) {} - - /// Reset an indexed color to original value - fn reset_color(&mut self, _: usize) {} - - /// Set the clipboard - fn set_clipboard(&mut self, _: &str) {} - - /// Run the dectest routine - fn dectest(&mut self) {} -} - -/// Describes shape of cursor -#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash, Deserialize)] -pub enum CursorStyle { - /// Cursor is a block like `▒` - Block, - - /// Cursor is an underscore like `_` - Underline, - - /// Cursor is a vertical bar `⎸` - Beam, - - /// Cursor is a box like `☐` - HollowBlock, - - /// Invisible cursor - Hidden, -} - -impl Default for CursorStyle { - fn default() -> CursorStyle { - CursorStyle::Block - } -} - -/// Terminal modes -#[derive(Debug, Eq, PartialEq)] -pub enum Mode { - /// ?1 - CursorKeys = 1, - /// Select 80 or 132 columns per page - /// - /// CSI ? 3 h -> set 132 column font - /// CSI ? 3 l -> reset 80 column font - /// - /// Additionally, - /// - /// * set margins to default positions - /// * erases all data in page memory - /// * resets DECLRMM to unavailable - /// * clears data from the status line (if set to host-writable) - DECCOLM = 3, - /// IRM Insert Mode - /// - /// NB should be part of non-private mode enum - /// - /// * `CSI 4 h` change to insert mode - /// * `CSI 4 l` reset to replacement mode - Insert = 4, - /// ?6 - Origin = 6, - /// ?7 - LineWrap = 7, - /// ?12 - BlinkingCursor = 12, - /// 20 - /// - /// NB This is actually a private mode. We should consider adding a second - /// enumeration for public/private modesets. - LineFeedNewLine = 20, - /// ?25 - ShowCursor = 25, - /// ?1000 - ReportMouseClicks = 1000, - /// ?1002 - ReportCellMouseMotion = 1002, - /// ?1003 - ReportAllMouseMotion = 1003, - /// ?1004 - ReportFocusInOut = 1004, - /// ?1006 - SgrMouse = 1006, - /// ?1049 - SwapScreenAndSetRestoreCursor = 1049, - /// ?2004 - BracketedPaste = 2004, -} - -impl Mode { - /// Create mode from a primitive - /// - /// TODO lots of unhandled values.. - pub fn from_primitive(private: bool, num: i64) -> Option<Mode> { - if private { - Some(match num { - 1 => Mode::CursorKeys, - 3 => Mode::DECCOLM, - 6 => Mode::Origin, - 7 => Mode::LineWrap, - 12 => Mode::BlinkingCursor, - 25 => Mode::ShowCursor, - 1000 => Mode::ReportMouseClicks, - 1002 => Mode::ReportCellMouseMotion, - 1003 => Mode::ReportAllMouseMotion, - 1004 => Mode::ReportFocusInOut, - 1006 => Mode::SgrMouse, - 1049 => Mode::SwapScreenAndSetRestoreCursor, - 2004 => Mode::BracketedPaste, - _ => { - trace!("[unimplemented] primitive mode: {}", num); - return None; - }, - }) - } else { - Some(match num { - 4 => Mode::Insert, - 20 => Mode::LineFeedNewLine, - _ => return None, - }) - } - } -} - -/// Mode for clearing line -/// -/// Relative to cursor -#[derive(Debug)] -pub enum LineClearMode { - /// Clear right of cursor - Right, - /// Clear left of cursor - Left, - /// Clear entire line - All, -} - -/// Mode for clearing terminal -/// -/// Relative to cursor -#[derive(Debug)] -pub enum ClearMode { - /// Clear below cursor - Below, - /// Clear above cursor - Above, - /// Clear entire terminal - All, - /// Clear 'saved' lines (scrollback) - Saved, -} - -/// Mode for clearing tab stops -#[derive(Debug)] -pub enum TabulationClearMode { - /// Clear stop under cursor - Current, - /// Clear all stops - All, -} - -/// Standard colors -/// -/// The order here matters since the enum should be castable to a `usize` for -/// indexing a color list. -#[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] -pub enum NamedColor { - /// Black - Black = 0, - /// Red - Red, - /// Green - Green, - /// Yellow - Yellow, - /// Blue - Blue, - /// Magenta - Magenta, - /// Cyan - Cyan, - /// White - White, - /// Bright black - BrightBlack, - /// Bright red - BrightRed, - /// Bright green - BrightGreen, - /// Bright yellow - BrightYellow, - /// Bright blue - BrightBlue, - /// Bright magenta - BrightMagenta, - /// Bright cyan - BrightCyan, - /// Bright white - BrightWhite, - /// The foreground color - Foreground = 256, - /// The background color - Background, - /// Color for the text under the cursor - CursorText, - /// Color for the cursor itself - Cursor, - /// Dim black - DimBlack, - /// Dim red - DimRed, - /// Dim green - DimGreen, - /// Dim yellow - DimYellow, - /// Dim blue - DimBlue, - /// Dim magenta - DimMagenta, - /// Dim cyan - DimCyan, - /// Dim white - DimWhite, - /// The bright foreground color - BrightForeground, - /// Dim foreground - DimForeground, -} - -impl NamedColor { - pub fn to_bright(self) -> Self { - match self { - NamedColor::Foreground => NamedColor::BrightForeground, - NamedColor::Black => NamedColor::BrightBlack, - NamedColor::Red => NamedColor::BrightRed, - NamedColor::Green => NamedColor::BrightGreen, - NamedColor::Yellow => NamedColor::BrightYellow, - NamedColor::Blue => NamedColor::BrightBlue, - NamedColor::Magenta => NamedColor::BrightMagenta, - NamedColor::Cyan => NamedColor::BrightCyan, - NamedColor::White => NamedColor::BrightWhite, - NamedColor::DimForeground => NamedColor::Foreground, - NamedColor::DimBlack => NamedColor::Black, - NamedColor::DimRed => NamedColor::Red, - NamedColor::DimGreen => NamedColor::Green, - NamedColor::DimYellow => NamedColor::Yellow, - NamedColor::DimBlue => NamedColor::Blue, - NamedColor::DimMagenta => NamedColor::Magenta, - NamedColor::DimCyan => NamedColor::Cyan, - NamedColor::DimWhite => NamedColor::White, - val => val, - } - } - - pub fn to_dim(self) -> Self { - match self { - NamedColor::Black => NamedColor::DimBlack, - NamedColor::Red => NamedColor::DimRed, - NamedColor::Green => NamedColor::DimGreen, - NamedColor::Yellow => NamedColor::DimYellow, - NamedColor::Blue => NamedColor::DimBlue, - NamedColor::Magenta => NamedColor::DimMagenta, - NamedColor::Cyan => NamedColor::DimCyan, - NamedColor::White => NamedColor::DimWhite, - NamedColor::Foreground => NamedColor::DimForeground, - NamedColor::BrightBlack => NamedColor::Black, - NamedColor::BrightRed => NamedColor::Red, - NamedColor::BrightGreen => NamedColor::Green, - NamedColor::BrightYellow => NamedColor::Yellow, - NamedColor::BrightBlue => NamedColor::Blue, - NamedColor::BrightMagenta => NamedColor::Magenta, - NamedColor::BrightCyan => NamedColor::Cyan, - NamedColor::BrightWhite => NamedColor::White, - NamedColor::BrightForeground => NamedColor::Foreground, - val => val, - } - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] -pub enum Color { - Named(NamedColor), - Spec(Rgb), - Indexed(u8), -} - -/// Terminal character attributes -#[derive(Debug, Eq, PartialEq)] -pub enum Attr { - /// Clear all special abilities - Reset, - /// Bold text - Bold, - /// Dim or secondary color - Dim, - /// Italic text - Italic, - /// Underscore text - Underscore, - /// Blink cursor slowly - BlinkSlow, - /// Blink cursor fast - BlinkFast, - /// Invert colors - Reverse, - /// Do not display characters - Hidden, - /// Strikeout text - Strike, - /// Cancel bold - CancelBold, - /// Cancel bold and dim - CancelBoldDim, - /// Cancel italic - CancelItalic, - /// Cancel underline - CancelUnderline, - /// Cancel blink - CancelBlink, - /// Cancel inversion - CancelReverse, - /// Cancel text hiding - CancelHidden, - /// Cancel strikeout - CancelStrike, - /// Set indexed foreground color - Foreground(Color), - /// Set indexed background color - Background(Color), -} - -/// Identifiers which can be assigned to a graphic character set -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum CharsetIndex { - /// Default set, is designated as ASCII at startup - G0, - G1, - G2, - G3, -} - -impl Default for CharsetIndex { - fn default() -> Self { - CharsetIndex::G0 - } -} - -/// Standard or common character sets which can be designated as G0-G3 -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum StandardCharset { - Ascii, - SpecialCharacterAndLineDrawing, -} - -impl Default for StandardCharset { - fn default() -> Self { - StandardCharset::Ascii - } -} - -impl<'a, H, W> vte::Perform for Performer<'a, H, W> -where - H: Handler + TermInfo + 'a, - W: io::Write + 'a, -{ - #[inline] - fn print(&mut self, c: char) { - self.handler.input(c); - self._state.preceding_char = Some(c); - } - - #[inline] - fn execute(&mut self, byte: u8) { - match byte { - C0::HT => self.handler.put_tab(1), - C0::BS => self.handler.backspace(), - C0::CR => self.handler.carriage_return(), - C0::LF | C0::VT | C0::FF => self.handler.linefeed(), - C0::BEL => self.handler.bell(), - C0::SUB => self.handler.substitute(), - C0::SI => self.handler.set_active_charset(CharsetIndex::G0), - C0::SO => self.handler.set_active_charset(CharsetIndex::G1), - 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), - } - } - - #[inline] - fn hook(&mut self, params: &[i64], intermediates: &[u8], ignore: bool) { - debug!( - "[unhandled hook] params={:?}, ints: {:?}, ignore: {:?}", - params, intermediates, ignore - ); - } - - #[inline] - fn put(&mut self, byte: u8) { - debug!("[unhandled put] byte={:?}", byte); - } - - #[inline] - fn unhook(&mut self) { - debug!("[unhandled unhook]"); - } - - // TODO replace OSC parsing with parser combinators - #[inline] - fn osc_dispatch(&mut self, params: &[&[u8]]) { - fn unhandled(params: &[&[u8]]) { - let mut buf = String::new(); - for items in params { - buf.push_str("["); - for item in *items { - buf.push_str(&format!("{:?},", *item as char)); - } - buf.push_str("],"); - } - debug!("[unhandled osc_dispatch]: [{}] at line {}", &buf, line!()); - } - - if params.is_empty() || params[0].is_empty() { - return; - } - - match params[0] { - // Set window title - b"0" | b"2" => { - if params.len() >= 2 { - if let Ok(utf8_title) = str::from_utf8(params[1]) { - self.handler.set_title(utf8_title); - return; - } - } - unhandled(params); - }, - - // Set icon name - // This is ignored, since alacritty has no concept of tabs - b"1" => return, - - // Set color index - b"4" => { - if params.len() > 1 && params.len() % 2 != 0 { - for chunk in params[1..].chunks(2) { - let index = parse_number(chunk[0]); - let color = parse_rgb_color(chunk[1]); - if let (Some(i), Some(c)) = (index, color) { - self.handler.set_color(i as usize, c); - return; - } - } - } - unhandled(params); - }, - - // Set foreground color - b"10" => { - if params.len() >= 2 { - if let Some(color) = parse_rgb_color(params[1]) { - self.handler.set_color(NamedColor::Foreground as usize, color); - return; - } - } - unhandled(params); - }, - - // Set background color - b"11" => { - if params.len() >= 2 { - if let Some(color) = parse_rgb_color(params[1]) { - self.handler.set_color(NamedColor::Background as usize, color); - return; - } - } - unhandled(params); - }, - - // Set text cursor color - b"12" => { - if params.len() >= 2 { - if let Some(color) = parse_rgb_color(params[1]) { - self.handler.set_color(NamedColor::Cursor as usize, color); - return; - } - } - unhandled(params); - }, - - // Set cursor style - b"50" => { - 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, - '2' => CursorStyle::Underline, - _ => return unhandled(params), - }; - self.handler.set_cursor_style(Some(style)); - return; - } - unhandled(params); - }, - - // Set clipboard - b"52" => { - if params.len() < 3 { - return unhandled(params); - } - |