Added a test with max, cludged a fix for resizing
This commit is contained in:
parent
ff44ddc077
commit
93dfc63f1c
6 changed files with 203 additions and 135 deletions
BIN
.swp
Normal file
BIN
.swp
Normal file
Binary file not shown.
|
@ -356,16 +356,16 @@
|
||||||
{
|
{
|
||||||
"context": "Terminal",
|
"context": "Terminal",
|
||||||
"bindings": {
|
"bindings": {
|
||||||
"ctrl-c": "terminal::SIGINT",
|
"ctrl-c": "terminal::Sigint",
|
||||||
"escape": "terminal::ESCAPE",
|
"escape": "terminal::Escape",
|
||||||
"ctrl-d": "terminal::Quit",
|
"ctrl-d": "terminal::Quit",
|
||||||
"backspace": "terminal::DEL",
|
"backspace": "terminal::Del",
|
||||||
"enter": "terminal::RETURN",
|
"enter": "terminal::Return",
|
||||||
"left": "terminal::LEFT",
|
"left": "terminal::Left",
|
||||||
"right": "terminal::RIGHT",
|
"right": "terminal::Right",
|
||||||
"up": "terminal::UP",
|
"up": "terminal::Up",
|
||||||
"down": "terminal::DOWN",
|
"down": "terminal::Down",
|
||||||
"tab": "terminal::TAB",
|
"tab": "terminal::Tab",
|
||||||
"cmd-v": "terminal::Paste"
|
"cmd-v": "terminal::Paste"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,3 +20,6 @@ smallvec = { version = "1.6", features = ["union"] }
|
||||||
mio-extras = "2.0.6"
|
mio-extras = "2.0.6"
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
ordered-float = "2.1.1"
|
ordered-float = "2.1.1"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
gpui = { path = "../gpui", features = ["test-support"] }
|
||||||
|
|
|
@ -22,7 +22,7 @@ use smallvec::SmallVec;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use workspace::{Item, Workspace};
|
use workspace::{Item, Workspace};
|
||||||
|
|
||||||
use crate::element::TerminalEl;
|
use crate::terminal_element::TerminalEl;
|
||||||
|
|
||||||
//ASCII Control characters on a keyboard
|
//ASCII Control characters on a keyboard
|
||||||
//Consts -> Structs -> Impls -> Functions, Vaguely in order of importance
|
//Consts -> Structs -> Impls -> Functions, Vaguely in order of importance
|
||||||
|
@ -37,16 +37,19 @@ const UP_SEQ: &str = "\x1b[A";
|
||||||
const DOWN_SEQ: &str = "\x1b[B";
|
const DOWN_SEQ: &str = "\x1b[B";
|
||||||
const DEFAULT_TITLE: &str = "Terminal";
|
const DEFAULT_TITLE: &str = "Terminal";
|
||||||
|
|
||||||
pub mod element;
|
pub mod terminal_element;
|
||||||
|
|
||||||
#[derive(Clone, Default, Debug, PartialEq, Eq)]
|
#[derive(Clone, Default, Debug, PartialEq, Eq)]
|
||||||
pub struct Input(pub String);
|
pub struct Input(pub String);
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub struct ScrollTerminal(pub i32);
|
||||||
|
|
||||||
actions!(
|
actions!(
|
||||||
terminal,
|
terminal,
|
||||||
[SIGINT, ESCAPE, DEL, RETURN, LEFT, RIGHT, UP, DOWN, TAB, Clear, Paste, Deploy, Quit]
|
[Sigint, Escape, Del, Return, Left, Right, Up, Down, Tab, Clear, Paste, Deploy, Quit]
|
||||||
);
|
);
|
||||||
impl_internal_actions!(terminal, [Input]);
|
impl_internal_actions!(terminal, [Input, ScrollTerminal]);
|
||||||
|
|
||||||
pub fn init(cx: &mut MutableAppContext) {
|
pub fn init(cx: &mut MutableAppContext) {
|
||||||
cx.add_action(Terminal::deploy);
|
cx.add_action(Terminal::deploy);
|
||||||
|
@ -62,6 +65,7 @@ pub fn init(cx: &mut MutableAppContext) {
|
||||||
cx.add_action(Terminal::down);
|
cx.add_action(Terminal::down);
|
||||||
cx.add_action(Terminal::tab);
|
cx.add_action(Terminal::tab);
|
||||||
cx.add_action(Terminal::paste);
|
cx.add_action(Terminal::paste);
|
||||||
|
cx.add_action(Terminal::scroll_terminal);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -74,15 +78,16 @@ impl EventListener for ZedListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
///A terminal renderer.
|
///A terminal renderer.
|
||||||
struct Terminal {
|
pub struct Terminal {
|
||||||
pty_tx: Notifier,
|
pty_tx: Notifier,
|
||||||
term: Arc<FairMutex<Term<ZedListener>>>,
|
term: Arc<FairMutex<Term<ZedListener>>>,
|
||||||
title: String,
|
title: String,
|
||||||
has_new_content: bool,
|
has_new_content: bool,
|
||||||
has_bell: bool, //Currently using iTerm bell, show bell emoji in tab until input is received
|
has_bell: bool, //Currently using iTerm bell, show bell emoji in tab until input is received
|
||||||
|
cur_size: SizeInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Event {
|
pub enum Event {
|
||||||
TitleChanged,
|
TitleChanged,
|
||||||
CloseTerminal,
|
CloseTerminal,
|
||||||
Activate,
|
Activate,
|
||||||
|
@ -124,7 +129,7 @@ impl Terminal {
|
||||||
};
|
};
|
||||||
|
|
||||||
//TODO figure out how to derive this better
|
//TODO figure out how to derive this better
|
||||||
let size_info = SizeInfo::new(400., 100.0, 5., 5., 0., 0., false);
|
let size_info = SizeInfo::new(200., 100.0, 5., 5., 0., 0., false);
|
||||||
|
|
||||||
//Set up the terminal...
|
//Set up the terminal...
|
||||||
let term = Term::new(&config, size_info, ZedListener(events_tx.clone()));
|
let term = Term::new(&config, size_info, ZedListener(events_tx.clone()));
|
||||||
|
@ -151,6 +156,7 @@ impl Terminal {
|
||||||
pty_tx,
|
pty_tx,
|
||||||
has_new_content: false,
|
has_new_content: false,
|
||||||
has_bell: false,
|
has_bell: false,
|
||||||
|
cur_size: size_info,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,6 +220,18 @@ impl Terminal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_size(&mut self, new_size: SizeInfo) {
|
||||||
|
if new_size != self.cur_size {
|
||||||
|
self.pty_tx.0.send(Msg::Resize(new_size)).ok();
|
||||||
|
self.term.lock().resize(new_size);
|
||||||
|
self.cur_size = new_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn scroll_terminal(&mut self, scroll: &ScrollTerminal, _: &mut ViewContext<Self>) {
|
||||||
|
self.term.lock().scroll_display(Scroll::Delta(scroll.0));
|
||||||
|
}
|
||||||
|
|
||||||
///Create a new Terminal
|
///Create a new Terminal
|
||||||
fn deploy(workspace: &mut Workspace, _: &Deploy, cx: &mut ViewContext<Workspace>) {
|
fn deploy(workspace: &mut Workspace, _: &Deploy, cx: &mut ViewContext<Workspace>) {
|
||||||
workspace.add_item(Box::new(cx.add_view(|cx| Terminal::new(cx))), cx);
|
workspace.add_item(Box::new(cx.add_view(|cx| Terminal::new(cx))), cx);
|
||||||
|
@ -242,39 +260,39 @@ impl Terminal {
|
||||||
self.pty_tx.notify(input.0.clone().into_bytes());
|
self.pty_tx.notify(input.0.clone().into_bytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn up(&mut self, _: &UP, cx: &mut ViewContext<Self>) {
|
fn up(&mut self, _: &Up, cx: &mut ViewContext<Self>) {
|
||||||
self.write_to_pty(&Input(UP_SEQ.to_string()), cx);
|
self.write_to_pty(&Input(UP_SEQ.to_string()), cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn down(&mut self, _: &DOWN, cx: &mut ViewContext<Self>) {
|
fn down(&mut self, _: &Down, cx: &mut ViewContext<Self>) {
|
||||||
self.write_to_pty(&Input(DOWN_SEQ.to_string()), cx);
|
self.write_to_pty(&Input(DOWN_SEQ.to_string()), cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tab(&mut self, _: &TAB, cx: &mut ViewContext<Self>) {
|
fn tab(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
|
||||||
self.write_to_pty(&Input(TAB_CHAR.to_string()), cx);
|
self.write_to_pty(&Input(TAB_CHAR.to_string()), cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send_sigint(&mut self, _: &SIGINT, cx: &mut ViewContext<Self>) {
|
fn send_sigint(&mut self, _: &Sigint, cx: &mut ViewContext<Self>) {
|
||||||
self.write_to_pty(&Input(ETX_CHAR.to_string()), cx);
|
self.write_to_pty(&Input(ETX_CHAR.to_string()), cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn escape(&mut self, _: &ESCAPE, cx: &mut ViewContext<Self>) {
|
fn escape(&mut self, _: &Escape, cx: &mut ViewContext<Self>) {
|
||||||
self.write_to_pty(&Input(ESC_CHAR.to_string()), cx);
|
self.write_to_pty(&Input(ESC_CHAR.to_string()), cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn del(&mut self, _: &DEL, cx: &mut ViewContext<Self>) {
|
fn del(&mut self, _: &Del, cx: &mut ViewContext<Self>) {
|
||||||
self.write_to_pty(&Input(DEL_CHAR.to_string()), cx);
|
self.write_to_pty(&Input(DEL_CHAR.to_string()), cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn carriage_return(&mut self, _: &RETURN, cx: &mut ViewContext<Self>) {
|
fn carriage_return(&mut self, _: &Return, cx: &mut ViewContext<Self>) {
|
||||||
self.write_to_pty(&Input(CARRIAGE_RETURN_CHAR.to_string()), cx);
|
self.write_to_pty(&Input(CARRIAGE_RETURN_CHAR.to_string()), cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn left(&mut self, _: &LEFT, cx: &mut ViewContext<Self>) {
|
fn left(&mut self, _: &Left, cx: &mut ViewContext<Self>) {
|
||||||
self.write_to_pty(&Input(LEFT_SEQ.to_string()), cx);
|
self.write_to_pty(&Input(LEFT_SEQ.to_string()), cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn right(&mut self, _: &RIGHT, cx: &mut ViewContext<Self>) {
|
fn right(&mut self, _: &Right, cx: &mut ViewContext<Self>) {
|
||||||
self.write_to_pty(&Input(RIGHT_SEQ.to_string()), cx);
|
self.write_to_pty(&Input(RIGHT_SEQ.to_string()), cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -291,20 +309,10 @@ impl View for Terminal {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut gpui::RenderContext<'_, Self>) -> ElementBox {
|
fn render(&mut self, cx: &mut gpui::RenderContext<'_, Self>) -> ElementBox {
|
||||||
let _theme = cx.global::<Settings>().theme.clone();
|
TerminalEl::new(cx.handle())
|
||||||
|
.contained()
|
||||||
//TODO: derive this
|
// .with_style(theme.terminal.container)
|
||||||
let size_info = SizeInfo::new(400., 100.0, 5., 5., 0., 0., false);
|
.boxed()
|
||||||
|
|
||||||
TerminalEl::new(
|
|
||||||
self.term.clone(),
|
|
||||||
self.pty_tx.0.clone(),
|
|
||||||
size_info,
|
|
||||||
cx.view_id(),
|
|
||||||
)
|
|
||||||
.contained()
|
|
||||||
// .with_style(theme.terminal.container)
|
|
||||||
.boxed()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
|
fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
|
||||||
|
@ -404,3 +412,32 @@ impl Item for Terminal {
|
||||||
matches!(event, &Event::Activate)
|
matches!(event, &Event::Activate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use crate::terminal_element::build_chunks;
|
||||||
|
use gpui::TestAppContext;
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
async fn test_terminal(cx: &mut TestAppContext) {
|
||||||
|
let terminal = cx.add_view(Default::default(), |cx| Terminal::new(cx));
|
||||||
|
|
||||||
|
terminal.update(cx, |terminal, cx| {
|
||||||
|
terminal.write_to_pty(&Input(("expr 3 + 4".to_string()).to_string()), cx);
|
||||||
|
terminal.carriage_return(&Return, cx);
|
||||||
|
});
|
||||||
|
|
||||||
|
terminal
|
||||||
|
.condition(cx, |terminal, _cx| {
|
||||||
|
let term = terminal.term.clone();
|
||||||
|
let (chunks, _) = build_chunks(
|
||||||
|
term.lock().renderable_content().display_iter,
|
||||||
|
&Default::default(),
|
||||||
|
);
|
||||||
|
let content = chunks.iter().map(|e| e.0.trim()).collect::<String>();
|
||||||
|
content.contains("7")
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
use alacritty_terminal::{
|
use alacritty_terminal::{
|
||||||
ansi::Color as AnsiColor,
|
ansi::Color as AnsiColor,
|
||||||
event_loop::Msg,
|
grid::{GridIterator, Indexed},
|
||||||
grid::{Indexed, Scroll},
|
|
||||||
index::Point,
|
index::Point,
|
||||||
sync::FairMutex,
|
|
||||||
term::{
|
term::{
|
||||||
cell::{Cell, Flags},
|
cell::{Cell, Flags},
|
||||||
SizeInfo,
|
SizeInfo,
|
||||||
},
|
},
|
||||||
Term,
|
|
||||||
};
|
};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
color::Color,
|
color::Color,
|
||||||
|
@ -17,38 +14,28 @@ use gpui::{
|
||||||
geometry::{rect::RectF, vector::vec2f},
|
geometry::{rect::RectF, vector::vec2f},
|
||||||
json::json,
|
json::json,
|
||||||
text_layout::Line,
|
text_layout::Line,
|
||||||
Event, MouseRegion, Quad,
|
Event, MouseRegion, PaintContext, Quad, WeakViewHandle,
|
||||||
};
|
};
|
||||||
use mio_extras::channel::Sender;
|
|
||||||
use ordered_float::OrderedFloat;
|
use ordered_float::OrderedFloat;
|
||||||
use settings::Settings;
|
use settings::Settings;
|
||||||
use std::{rc::Rc, sync::Arc};
|
use std::rc::Rc;
|
||||||
use theme::TerminalStyle;
|
use theme::TerminalStyle;
|
||||||
|
|
||||||
use crate::{Input, ZedListener};
|
use crate::{Input, ScrollTerminal, Terminal};
|
||||||
|
|
||||||
const ALACRITTY_SCROLL_MULTIPLIER: f32 = 3.;
|
const ALACRITTY_SCROLL_MULTIPLIER: f32 = 3.;
|
||||||
|
const MAGIC_VISUAL_WIDTH_MULTIPLIER: f32 = 1.28; //1/8th + .003 so we bias long instead of short
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
const DEBUG_GRID: bool = false;
|
||||||
|
|
||||||
pub struct TerminalEl {
|
pub struct TerminalEl {
|
||||||
term: Arc<FairMutex<Term<ZedListener>>>,
|
view: WeakViewHandle<Terminal>,
|
||||||
pty_tx: Sender<Msg>,
|
|
||||||
size: SizeInfo,
|
|
||||||
view_id: usize,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TerminalEl {
|
impl TerminalEl {
|
||||||
pub fn new(
|
pub fn new(view: WeakViewHandle<Terminal>) -> TerminalEl {
|
||||||
term: Arc<FairMutex<Term<ZedListener>>>,
|
TerminalEl { view }
|
||||||
pty_tx: Sender<Msg>,
|
|
||||||
size: SizeInfo,
|
|
||||||
view_id: usize,
|
|
||||||
) -> TerminalEl {
|
|
||||||
TerminalEl {
|
|
||||||
term,
|
|
||||||
pty_tx,
|
|
||||||
size,
|
|
||||||
view_id,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,6 +44,7 @@ pub struct LayoutState {
|
||||||
line_height: f32,
|
line_height: f32,
|
||||||
em_width: f32,
|
em_width: f32,
|
||||||
cursor: Option<RectF>,
|
cursor: Option<RectF>,
|
||||||
|
cur_size: SizeInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Element for TerminalEl {
|
impl Element for TerminalEl {
|
||||||
|
@ -68,88 +56,56 @@ impl Element for TerminalEl {
|
||||||
constraint: gpui::SizeConstraint,
|
constraint: gpui::SizeConstraint,
|
||||||
cx: &mut gpui::LayoutContext,
|
cx: &mut gpui::LayoutContext,
|
||||||
) -> (gpui::geometry::vector::Vector2F, Self::LayoutState) {
|
) -> (gpui::geometry::vector::Vector2F, Self::LayoutState) {
|
||||||
|
let view = self.view.upgrade(cx).unwrap();
|
||||||
let size = constraint.max;
|
let size = constraint.max;
|
||||||
let settings = cx.global::<Settings>();
|
let settings = cx.global::<Settings>();
|
||||||
let editor_theme = &settings.theme.editor;
|
let editor_theme = &settings.theme.editor;
|
||||||
let terminal_theme = &settings.theme.terminal;
|
|
||||||
//Get terminal
|
|
||||||
let mut term = self.term.lock();
|
|
||||||
|
|
||||||
//Set up text rendering
|
//Set up text rendering
|
||||||
let font_cache = cx.font_cache();
|
|
||||||
|
|
||||||
let font_family_id = settings.buffer_font_family;
|
|
||||||
let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
|
|
||||||
let font_properties = Default::default();
|
|
||||||
let font_id = font_cache
|
|
||||||
.select_font(font_family_id, &font_properties)
|
|
||||||
.unwrap();
|
|
||||||
let font_size = settings.buffer_font_size;
|
|
||||||
|
|
||||||
let text_style = TextStyle {
|
let text_style = TextStyle {
|
||||||
color: editor_theme.text_color,
|
color: editor_theme.text_color,
|
||||||
font_family_id: settings.buffer_font_family,
|
font_family_id: settings.buffer_font_family,
|
||||||
font_family_name,
|
font_family_name: cx
|
||||||
font_id,
|
.font_cache()
|
||||||
font_size,
|
.family_name(settings.buffer_font_family)
|
||||||
|
.unwrap(),
|
||||||
|
font_id: cx
|
||||||
|
.font_cache()
|
||||||
|
.select_font(settings.buffer_font_family, &Default::default())
|
||||||
|
.unwrap(),
|
||||||
|
font_size: settings.buffer_font_size,
|
||||||
font_properties: Default::default(),
|
font_properties: Default::default(),
|
||||||
underline: Default::default(),
|
underline: Default::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let line_height = cx.font_cache.line_height(text_style.font_size);
|
let line_height = cx.font_cache.line_height(text_style.font_size);
|
||||||
let em_width = cx
|
let cell_width = cx
|
||||||
.font_cache()
|
.font_cache()
|
||||||
.em_width(text_style.font_id, text_style.font_size)
|
.em_width(text_style.font_id, text_style.font_size)
|
||||||
+ 2.;
|
* MAGIC_VISUAL_WIDTH_MULTIPLIER;
|
||||||
|
|
||||||
//Resize terminal
|
let new_size = SizeInfo::new(
|
||||||
let new_size = SizeInfo::new(size.x(), size.y(), em_width, line_height, 0., 0., false);
|
size.x() - cell_width, //Padding. Really should make this more explicit
|
||||||
if !new_size.eq(&self.size) {
|
size.y(),
|
||||||
self.pty_tx.send(Msg::Resize(new_size)).ok();
|
cell_width,
|
||||||
term.resize(new_size);
|
line_height,
|
||||||
self.size = new_size;
|
0.,
|
||||||
}
|
0.,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
view.update(cx.app, |view, _cx| {
|
||||||
|
view.set_size(new_size);
|
||||||
|
});
|
||||||
|
|
||||||
|
let settings = cx.global::<Settings>();
|
||||||
|
let terminal_theme = &settings.theme.terminal;
|
||||||
|
let term = view.read(cx).term.lock();
|
||||||
|
|
||||||
//Start rendering
|
|
||||||
let content = term.renderable_content();
|
let content = term.renderable_content();
|
||||||
|
let (chunks, line_count) = build_chunks(content.display_iter, &terminal_theme);
|
||||||
let mut lines: Vec<(String, Option<HighlightStyle>)> = vec![];
|
|
||||||
let mut last_line = 0;
|
|
||||||
let mut line_count = 1;
|
|
||||||
let mut cur_chunk = String::new();
|
|
||||||
|
|
||||||
let mut cur_highlight = HighlightStyle {
|
|
||||||
color: Some(Color::white()),
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
for cell in content.display_iter {
|
|
||||||
let Indexed {
|
|
||||||
point: Point { line, .. },
|
|
||||||
cell: Cell {
|
|
||||||
c, fg, flags, .. // TODO: Add bg and flags
|
|
||||||
}, //TODO: Learn what 'CellExtra does'
|
|
||||||
} = cell;
|
|
||||||
|
|
||||||
let new_highlight = make_style_from_cell(fg, flags, &terminal_theme);
|
|
||||||
|
|
||||||
if line != last_line {
|
|
||||||
line_count += 1;
|
|
||||||
cur_chunk.push('\n');
|
|
||||||
last_line = line.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if new_highlight != cur_highlight {
|
|
||||||
lines.push((cur_chunk.clone(), Some(cur_highlight.clone())));
|
|
||||||
cur_chunk.clear();
|
|
||||||
cur_highlight = new_highlight;
|
|
||||||
}
|
|
||||||
cur_chunk.push(*c)
|
|
||||||
}
|
|
||||||
lines.push((cur_chunk, Some(cur_highlight)));
|
|
||||||
|
|
||||||
let shaped_lines = layout_highlighted_chunks(
|
let shaped_lines = layout_highlighted_chunks(
|
||||||
lines.iter().map(|(text, style)| (text.as_str(), *style)),
|
chunks.iter().map(|(text, style)| (text.as_str(), *style)),
|
||||||
&text_style,
|
&text_style,
|
||||||
cx.text_layout_cache,
|
cx.text_layout_cache,
|
||||||
&cx.font_cache,
|
&cx.font_cache,
|
||||||
|
@ -167,7 +123,7 @@ impl Element for TerminalEl {
|
||||||
let cursor_x = layout_line.x_for_index(content.cursor.point.column.0);
|
let cursor_x = layout_line.x_for_index(content.cursor.point.column.0);
|
||||||
cursor = Some(RectF::new(
|
cursor = Some(RectF::new(
|
||||||
vec2f(cursor_x, cursor_line as f32 * line_height),
|
vec2f(cursor_x, cursor_line as f32 * line_height),
|
||||||
vec2f(em_width, line_height),
|
vec2f(cell_width, line_height),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,8 +132,9 @@ impl Element for TerminalEl {
|
||||||
LayoutState {
|
LayoutState {
|
||||||
lines: shaped_lines,
|
lines: shaped_lines,
|
||||||
line_height,
|
line_height,
|
||||||
em_width,
|
em_width: cell_width,
|
||||||
cursor,
|
cursor,
|
||||||
|
cur_size: new_size,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -192,7 +149,7 @@ impl Element for TerminalEl {
|
||||||
cx.scene.push_layer(Some(visible_bounds));
|
cx.scene.push_layer(Some(visible_bounds));
|
||||||
|
|
||||||
cx.scene.push_mouse_region(MouseRegion {
|
cx.scene.push_mouse_region(MouseRegion {
|
||||||
view_id: self.view_id,
|
view_id: self.view.id(),
|
||||||
discriminant: None,
|
discriminant: None,
|
||||||
bounds: visible_bounds,
|
bounds: visible_bounds,
|
||||||
hover: None,
|
hover: None,
|
||||||
|
@ -205,7 +162,7 @@ impl Element for TerminalEl {
|
||||||
right_mouse_down_out: None,
|
right_mouse_down_out: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
let origin = bounds.origin() + vec2f(layout.em_width, 0.);
|
let origin = bounds.origin() + vec2f(layout.em_width, 0.); //Padding
|
||||||
|
|
||||||
let mut line_origin = origin;
|
let mut line_origin = origin;
|
||||||
for line in &layout.lines {
|
for line in &layout.lines {
|
||||||
|
@ -229,6 +186,11 @@ impl Element for TerminalEl {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
if DEBUG_GRID {
|
||||||
|
draw_debug_grid(bounds, layout, cx);
|
||||||
|
}
|
||||||
|
|
||||||
cx.scene.pop_layer();
|
cx.scene.pop_layer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,8 +210,7 @@ impl Element for TerminalEl {
|
||||||
if visible_bounds.contains_point(*position) {
|
if visible_bounds.contains_point(*position) {
|
||||||
let vertical_scroll =
|
let vertical_scroll =
|
||||||
(delta.y() / layout.line_height) * ALACRITTY_SCROLL_MULTIPLIER;
|
(delta.y() / layout.line_height) * ALACRITTY_SCROLL_MULTIPLIER;
|
||||||
let scroll = Scroll::Delta(vertical_scroll.round() as i32);
|
cx.dispatch_action(ScrollTerminal(vertical_scroll.round() as i32));
|
||||||
self.term.lock().scroll_display(scroll);
|
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
@ -282,6 +243,47 @@ impl Element for TerminalEl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn build_chunks(
|
||||||
|
grid_iterator: GridIterator<Cell>,
|
||||||
|
theme: &TerminalStyle,
|
||||||
|
) -> (Vec<(String, Option<HighlightStyle>)>, usize) {
|
||||||
|
let mut lines: Vec<(String, Option<HighlightStyle>)> = vec![];
|
||||||
|
let mut last_line = 0;
|
||||||
|
let mut line_count = 1;
|
||||||
|
let mut cur_chunk = String::new();
|
||||||
|
|
||||||
|
let mut cur_highlight = HighlightStyle {
|
||||||
|
color: Some(Color::white()),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
for cell in grid_iterator {
|
||||||
|
let Indexed {
|
||||||
|
point: Point { line, .. },
|
||||||
|
cell: Cell {
|
||||||
|
c, fg, flags, .. // TODO: Add bg and flags
|
||||||
|
}, //TODO: Learn what 'CellExtra does'
|
||||||
|
} = cell;
|
||||||
|
|
||||||
|
let new_highlight = make_style_from_cell(fg, flags, theme);
|
||||||
|
|
||||||
|
if line != last_line {
|
||||||
|
line_count += 1;
|
||||||
|
cur_chunk.push('\n');
|
||||||
|
last_line = line.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if new_highlight != cur_highlight {
|
||||||
|
lines.push((cur_chunk.clone(), Some(cur_highlight.clone())));
|
||||||
|
cur_chunk.clear();
|
||||||
|
cur_highlight = new_highlight;
|
||||||
|
}
|
||||||
|
cur_chunk.push(*c)
|
||||||
|
}
|
||||||
|
lines.push((cur_chunk, Some(cur_highlight)));
|
||||||
|
(lines, line_count)
|
||||||
|
}
|
||||||
|
|
||||||
fn make_style_from_cell(fg: &AnsiColor, flags: &Flags, style: &TerminalStyle) -> HighlightStyle {
|
fn make_style_from_cell(fg: &AnsiColor, flags: &Flags, style: &TerminalStyle) -> HighlightStyle {
|
||||||
let fg = Some(alac_color_to_gpui_color(fg, style));
|
let fg = Some(alac_color_to_gpui_color(fg, style));
|
||||||
let underline = if flags.contains(Flags::UNDERLINE) {
|
let underline = if flags.contains(Flags::UNDERLINE) {
|
||||||
|
@ -337,3 +339,32 @@ fn alac_color_to_gpui_color(allac_color: &AnsiColor, style: &TerminalStyle) -> C
|
||||||
alacritty_terminal::ansi::Color::Indexed(_) => Color::white(), //Color cube weirdness
|
alacritty_terminal::ansi::Color::Indexed(_) => Color::white(), //Color cube weirdness
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
fn draw_debug_grid(bounds: RectF, layout: &mut LayoutState, cx: &mut PaintContext) {
|
||||||
|
let width = layout.cur_size.width();
|
||||||
|
let height = layout.cur_size.height();
|
||||||
|
//Alacritty uses 'as usize', so shall we.
|
||||||
|
for col in 0..(width / layout.em_width).round() as usize {
|
||||||
|
cx.scene.push_quad(Quad {
|
||||||
|
bounds: RectF::new(
|
||||||
|
bounds.origin() + vec2f((col + 1) as f32 * layout.em_width, 0.),
|
||||||
|
vec2f(1., height),
|
||||||
|
),
|
||||||
|
background: Some(Color::green()),
|
||||||
|
border: Default::default(),
|
||||||
|
corner_radius: 0.,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
for row in 0..((height / layout.line_height) + 1.0).round() as usize {
|
||||||
|
cx.scene.push_quad(Quad {
|
||||||
|
bounds: RectF::new(
|
||||||
|
bounds.origin() + vec2f(layout.em_width, row as f32 * layout.line_height),
|
||||||
|
vec2f(width, 1.),
|
||||||
|
),
|
||||||
|
background: Some(Color::green()),
|
||||||
|
border: Default::default(),
|
||||||
|
corner_radius: 0.,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,7 +25,4 @@ const ramps = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const dark = createTheme(`${name}-dark`, false, ramps);
|
export const dark = createTheme(`${name}-dark`, false, ramps);
|
||||||
export const light = createTheme(`${name}-light`, true, ramps);
|
export const light = createTheme(`${name}-light`, true, ramps);
|
||||||
|
|
||||||
console.log(JSON.stringify(dark.ramps.neutral.domain()))
|
|
||||||
console.log(JSON.stringify(light.ramps.neutral.domain()))
|
|
Loading…
Add table
Add a link
Reference in a new issue