mirror of https://github.com/lapce/lapce.git
terminal keyboard
This commit is contained in:
parent
1ef920b19f
commit
1bdc28ca5f
|
@ -21,7 +21,7 @@
|
|||
data::EditorKind,
|
||||
editor::{EditorLocation, EditorLocationNew, HighlightTextLayout},
|
||||
palette::{NewPaletteItem, PaletteType},
|
||||
proxy::TerminalContent,
|
||||
proxy::{CursorShape, TerminalContent},
|
||||
split::SplitMoveDirection,
|
||||
state::LapceWorkspace,
|
||||
};
|
||||
|
@ -376,7 +376,12 @@ pub enum LapceUICommand {
|
|||
UpdateLineChanges(BufferId),
|
||||
PublishDiagnostics(PublishDiagnosticsParams),
|
||||
UpdateDiffFiles(Vec<PathBuf>),
|
||||
TerminalUpdateContent(TermId, TerminalContent),
|
||||
TerminalUpdateContent(
|
||||
TermId,
|
||||
TerminalContent,
|
||||
alacritty_terminal::index::Point,
|
||||
CursorShape,
|
||||
),
|
||||
ReloadBuffer(BufferId, u64, String),
|
||||
EnsureVisible((Rect, (f64, f64), Option<EnsureVisiblePosition>)),
|
||||
EnsureRectVisible(Rect),
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
use directories::ProjectDirs;
|
||||
use druid::{
|
||||
piet::{PietText, Text, TextLayout, TextLayoutBuilder},
|
||||
theme, Color, Env, FontDescriptor, FontFamily, Key,
|
||||
theme, Color, Env, FontDescriptor, FontFamily, Key, Size,
|
||||
};
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
|
||||
|
@ -37,6 +37,10 @@ impl LapceTheme {
|
|||
pub const EDITOR_SELECTION: &'static str = "editor.selection";
|
||||
pub const EDITOR_CURRENT_LINE: &'static str = "editor.current_line";
|
||||
|
||||
pub const TERMINAL_CURSOR: &'static str = "terminal.cursor";
|
||||
pub const TERMINAL_BACKGROUND: &'static str = "terminal.background";
|
||||
pub const TERMINAL_FOREGROUND: &'static str = "terminal.foreground";
|
||||
|
||||
pub const PALETTE_BACKGROUND: &'static str = "palette.background";
|
||||
pub const PALETTE_CURRENT: &'static str = "palette.current";
|
||||
|
||||
|
@ -183,6 +187,15 @@ pub fn editor_text_width(&self, text: &mut PietText, c: &str) -> f64 {
|
|||
text_layout.size().width
|
||||
}
|
||||
|
||||
pub fn editor_text_size(&self, text: &mut PietText, c: &str) -> Size {
|
||||
let text_layout = text
|
||||
.new_text_layout(c.to_string())
|
||||
.font(self.editor.font_family(), self.editor.font_size as f64)
|
||||
.build()
|
||||
.unwrap();
|
||||
text_layout.size()
|
||||
}
|
||||
|
||||
pub fn reload_env(&self, env: &mut Env) {
|
||||
env.set(theme::SCROLLBAR_RADIUS, 0.0);
|
||||
env.set(theme::SCROLLBAR_EDGE_WIDTH, 0.0);
|
||||
|
|
|
@ -53,6 +53,9 @@ pub struct KeyMap {
|
|||
pub trait KeyPressFocus {
|
||||
fn get_mode(&self) -> Mode;
|
||||
fn check_condition(&self, condition: &str) -> bool;
|
||||
fn is_terminal(&self) -> bool {
|
||||
false
|
||||
}
|
||||
fn run_command(
|
||||
&mut self,
|
||||
ctx: &mut EventCtx,
|
||||
|
@ -236,7 +239,8 @@ fn match_keymap<T: KeyPressFocus>(
|
|||
.iter()
|
||||
.filter(|keymap| {
|
||||
if keymap.modes.len() > 0
|
||||
&& !keymap.modes.contains(&check.get_mode())
|
||||
&& (!keymap.modes.contains(&check.get_mode())
|
||||
|| check.is_terminal())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -354,6 +354,24 @@ pub fn stop(&self) {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum CursorShape {
|
||||
/// 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,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[serde(tag = "method", content = "params")]
|
||||
|
@ -383,6 +401,8 @@ pub enum Notification {
|
|||
TerminalUpdateContent {
|
||||
id: TermId,
|
||||
content: TerminalContent,
|
||||
cursor_shape: CursorShape,
|
||||
cursor_point: alacritty_terminal::index::Point,
|
||||
},
|
||||
DiffFiles {
|
||||
files: Vec<PathBuf>,
|
||||
|
@ -426,7 +446,7 @@ fn handle_notification(
|
|||
Notification::ListDir { mut items } => {}
|
||||
Notification::DiffFiles { files } => {}
|
||||
Notification::PublishDiagnostics { diagnostics } => {}
|
||||
Notification::TerminalUpdateContent { id, content } => {}
|
||||
Notification::TerminalUpdateContent { id, content, .. } => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -561,10 +581,20 @@ fn handle_notification(
|
|||
Target::Widget(self.tab_id),
|
||||
);
|
||||
}
|
||||
Notification::TerminalUpdateContent { id, content } => {
|
||||
Notification::TerminalUpdateContent {
|
||||
id,
|
||||
content,
|
||||
cursor_shape,
|
||||
cursor_point,
|
||||
} => {
|
||||
self.event_sink.submit_command(
|
||||
LAPCE_UI_COMMAND,
|
||||
LapceUICommand::TerminalUpdateContent(id, content),
|
||||
LapceUICommand::TerminalUpdateContent(
|
||||
id,
|
||||
content,
|
||||
cursor_point,
|
||||
cursor_shape,
|
||||
),
|
||||
Target::Widget(self.tab_id),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -226,12 +226,20 @@ fn event(
|
|||
Arc::make_mut(buffer).load_content(content);
|
||||
ctx.set_handled();
|
||||
}
|
||||
LapceUICommand::TerminalUpdateContent(id, content) => {
|
||||
LapceUICommand::TerminalUpdateContent(
|
||||
id,
|
||||
content,
|
||||
cursor_point,
|
||||
cursor_shape,
|
||||
) => {
|
||||
let terminal = Arc::make_mut(&mut data.terminal)
|
||||
.terminals
|
||||
.get_mut(id)
|
||||
.unwrap();
|
||||
Arc::make_mut(terminal).content = content.to_owned();
|
||||
let terminal = Arc::make_mut(terminal);
|
||||
terminal.content = content.to_owned();
|
||||
terminal.cursor_point = cursor_point.to_owned();
|
||||
terminal.cursor_shape = cursor_shape.to_owned();
|
||||
ctx.set_handled();
|
||||
}
|
||||
LapceUICommand::UpdateDiffFiles(files) => {
|
||||
|
|
|
@ -1,22 +1,30 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use alacritty_terminal::ansi;
|
||||
use druid::{
|
||||
piet::{Text, TextLayoutBuilder},
|
||||
BoxConstraints, Data, Env, Event, EventCtx, LayoutCtx, LifeCycle, LifeCycleCtx,
|
||||
PaintCtx, Point, RenderContext, Size, UpdateCtx, Widget, WidgetExt, WidgetId,
|
||||
WidgetPod,
|
||||
BoxConstraints, Color, Data, Env, Event, EventCtx, KbKey, LayoutCtx, LifeCycle,
|
||||
LifeCycleCtx, Modifiers, PaintCtx, Point, RenderContext, Size, UpdateCtx,
|
||||
Widget, WidgetExt, WidgetId, WidgetPod,
|
||||
};
|
||||
use lapce_proxy::terminal::TermId;
|
||||
|
||||
use crate::{
|
||||
command::LapceCommand,
|
||||
config::LapceTheme,
|
||||
data::LapceTabData,
|
||||
keypress::KeyPressFocus,
|
||||
proxy::{LapceProxy, TerminalContent},
|
||||
proxy::{CursorShape, LapceProxy, TerminalContent},
|
||||
scroll::LapcePadding,
|
||||
split::LapceSplitNew,
|
||||
state::Mode,
|
||||
};
|
||||
|
||||
const CTRL_CHARS: &'static [char] = &[
|
||||
'@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
|
||||
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '[', '\\', ']', '^', '_',
|
||||
];
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct TerminalSplitData {
|
||||
pub widget_id: WidgetId,
|
||||
|
@ -46,18 +54,25 @@ pub struct LapceTerminalViewData {
|
|||
}
|
||||
|
||||
impl KeyPressFocus for LapceTerminalViewData {
|
||||
fn is_terminal(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn get_mode(&self) -> Mode {
|
||||
Mode::Insert
|
||||
}
|
||||
|
||||
fn check_condition(&self, condition: &str) -> bool {
|
||||
false
|
||||
match condition {
|
||||
"terminal_focus" => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn run_command(
|
||||
&mut self,
|
||||
ctx: &mut EventCtx,
|
||||
command: &crate::command::LapceCommand,
|
||||
command: &LapceCommand,
|
||||
count: Option<usize>,
|
||||
env: &Env,
|
||||
) {
|
||||
|
@ -72,6 +87,8 @@ fn insert(&mut self, ctx: &mut EventCtx, c: &str) {
|
|||
pub struct LapceTerminalData {
|
||||
id: TermId,
|
||||
pub content: TerminalContent,
|
||||
pub cursor_point: alacritty_terminal::index::Point,
|
||||
pub cursor_shape: CursorShape,
|
||||
}
|
||||
|
||||
impl LapceTerminalData {
|
||||
|
@ -83,6 +100,8 @@ pub fn new(proxy: Arc<LapceProxy>) -> Self {
|
|||
Self {
|
||||
id,
|
||||
content: TerminalContent::new(),
|
||||
cursor_point: alacritty_terminal::index::Point::default(),
|
||||
cursor_shape: CursorShape::Block,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -95,7 +114,7 @@ pub struct TerminalPanel {
|
|||
impl TerminalPanel {
|
||||
pub fn new(data: &LapceTabData) -> Self {
|
||||
let (term_id, _) = data.terminal.terminals.iter().next().unwrap();
|
||||
let terminal = LapceTerminal::new(*term_id);
|
||||
let terminal = LapcePadding::new(10.0, LapceTerminal::new(*term_id));
|
||||
let split = LapceSplitNew::new(data.terminal.split_id).with_flex_child(
|
||||
terminal.boxed(),
|
||||
None,
|
||||
|
@ -211,12 +230,42 @@ fn event(
|
|||
}
|
||||
Event::KeyDown(key_event) => {
|
||||
let mut keypress = data.keypress.clone();
|
||||
Arc::make_mut(&mut keypress).key_down(
|
||||
if !Arc::make_mut(&mut keypress).key_down(
|
||||
ctx,
|
||||
key_event,
|
||||
&mut term_data,
|
||||
env,
|
||||
);
|
||||
) {
|
||||
let s = match &key_event.key {
|
||||
KbKey::Character(c) => {
|
||||
let mut s = "".to_string();
|
||||
let mut mods = key_event.mods.clone();
|
||||
if mods.ctrl() {
|
||||
mods.set(Modifiers::CONTROL, false);
|
||||
if mods.is_empty() && c.chars().count() == 1 {
|
||||
let c = c.chars().next().unwrap();
|
||||
if let Some(i) =
|
||||
CTRL_CHARS.iter().position(|e| &c == e)
|
||||
{
|
||||
s = char::from_u32(i as u32)
|
||||
.unwrap()
|
||||
.to_string()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s
|
||||
}
|
||||
KbKey::Backspace => "\x08".to_string(),
|
||||
KbKey::Tab => "\x09".to_string(),
|
||||
KbKey::Enter => "\x0a".to_string(),
|
||||
KbKey::Escape => "\x1b".to_string(),
|
||||
_ => "".to_string(),
|
||||
};
|
||||
if s != "" {
|
||||
data.proxy.terminal_insert(self.term_id, &s);
|
||||
}
|
||||
}
|
||||
data.keypress = keypress.clone();
|
||||
}
|
||||
_ => (),
|
||||
|
@ -235,6 +284,12 @@ fn lifecycle(
|
|||
data: &LapceTabData,
|
||||
env: &Env,
|
||||
) {
|
||||
match event {
|
||||
LifeCycle::FocusChanged(_) => {
|
||||
ctx.request_paint();
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn update(
|
||||
|
@ -259,21 +314,64 @@ fn layout(
|
|||
self.height = size.height;
|
||||
let width = data.config.editor_text_width(ctx.text(), "W");
|
||||
let line_height = data.config.editor.line_height as f64;
|
||||
let width = (self.width / width).ceil() as usize;
|
||||
let height = (self.height / line_height).ceil() as usize;
|
||||
let width = (self.width / width).floor() as usize;
|
||||
let height = (self.height / line_height).floor() as usize;
|
||||
data.proxy.terminal_resize(self.term_id, width, height);
|
||||
}
|
||||
size
|
||||
}
|
||||
|
||||
fn paint(&mut self, ctx: &mut PaintCtx, data: &LapceTabData, env: &Env) {
|
||||
let width = data.config.editor_text_width(ctx.text(), "W");
|
||||
let char_size = data.config.editor_text_size(ctx.text(), "W");
|
||||
let char_width = char_size.width;
|
||||
let line_height = data.config.editor.line_height as f64;
|
||||
let y_shift = (line_height - char_size.height) / 2.0;
|
||||
|
||||
let terminal = data.terminal.terminals.get(&self.term_id).unwrap();
|
||||
|
||||
let rect =
|
||||
Size::new(char_width, line_height)
|
||||
.to_rect()
|
||||
.with_origin(Point::new(
|
||||
terminal.cursor_point.column.0 as f64 * char_width,
|
||||
terminal.cursor_point.line.0 as f64 * line_height,
|
||||
));
|
||||
if ctx.is_focused() {
|
||||
ctx.fill(
|
||||
rect,
|
||||
data.config.get_color_unchecked(LapceTheme::TERMINAL_CURSOR),
|
||||
);
|
||||
} else {
|
||||
ctx.stroke(
|
||||
rect,
|
||||
data.config.get_color_unchecked(LapceTheme::TERMINAL_CURSOR),
|
||||
1.0,
|
||||
);
|
||||
}
|
||||
|
||||
for (p, cell) in terminal.content.iter() {
|
||||
let x = p.column.0 as f64 * width;
|
||||
let y = p.line.0 as f64 * line_height;
|
||||
let x = p.column.0 as f64 * char_width;
|
||||
let y = p.line.0 as f64 * line_height + y_shift;
|
||||
let fg = match cell.fg {
|
||||
ansi::Color::Named(color) => {
|
||||
let color = match color {
|
||||
ansi::NamedColor::Cursor => LapceTheme::TERMINAL_CURSOR,
|
||||
ansi::NamedColor::Foreground => {
|
||||
LapceTheme::TERMINAL_FOREGROUND
|
||||
}
|
||||
ansi::NamedColor::Background => {
|
||||
LapceTheme::TERMINAL_BACKGROUND
|
||||
}
|
||||
_ => LapceTheme::TERMINAL_FOREGROUND,
|
||||
};
|
||||
data.config.get_color_unchecked(color).clone()
|
||||
}
|
||||
ansi::Color::Spec(rgb) => Color::rgb8(rgb.r, rgb.g, rgb.b),
|
||||
ansi::Color::Indexed(index) => data
|
||||
.config
|
||||
.get_color_unchecked(LapceTheme::TERMINAL_FOREGROUND)
|
||||
.clone(),
|
||||
};
|
||||
let text_layout = ctx
|
||||
.text()
|
||||
.new_text_layout(cell.c.to_string())
|
||||
|
@ -281,6 +379,7 @@ fn paint(&mut self, ctx: &mut PaintCtx, data: &LapceTabData, env: &Env) {
|
|||
data.config.editor.font_family(),
|
||||
data.config.editor.font_size as f64,
|
||||
)
|
||||
.text_color(fg)
|
||||
.build()
|
||||
.unwrap();
|
||||
ctx.draw_text(&text_layout, Point::new(x, y));
|
||||
|
|
|
@ -17,6 +17,10 @@ cyan = "#56b6c2"
|
|||
"lapce.dropdown_shadow" = "#000000"
|
||||
"lapce.border" = "#000000"
|
||||
|
||||
"terminal.cursor" = "$white"
|
||||
"terminal.foreground" = "$white"
|
||||
"terminal.background" = "$black"
|
||||
|
||||
"editor.background" = "$black"
|
||||
"editor.foreground" = "$white"
|
||||
"editor.dim" = "#A0A1A7"
|
||||
|
|
|
@ -487,6 +487,21 @@ key = "meta+;"
|
|||
command = "split_vertical"
|
||||
mode = "n"
|
||||
|
||||
[[keymaps]]
|
||||
key = "meta+;"
|
||||
command = "split_vertical"
|
||||
when = "terminal_focus"
|
||||
|
||||
[[keymaps]]
|
||||
key = "meta+l"
|
||||
command = "split_right"
|
||||
when = "terminal_focus"
|
||||
|
||||
[[keymaps]]
|
||||
key = "meta+h"
|
||||
command = "split_left"
|
||||
when = "terminal_focus"
|
||||
|
||||
[[keymaps]]
|
||||
key = "meta+g"
|
||||
command = "split_horizontal"
|
||||
|
|
|
@ -16,6 +16,10 @@ cyan = "#0184bc"
|
|||
"lapce.dropdown_shadow" = "#b4b4b4"
|
||||
"lapce.border" = "#b4b4b4"
|
||||
|
||||
"terminal.cursor" = "$black"
|
||||
"terminal.foreground" = "$black"
|
||||
"terminal.background" = "$white"
|
||||
|
||||
"editor.background" = "$white"
|
||||
"editor.foreground" = "$black"
|
||||
"editor.dim" = "#A0A1A7"
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
use crate::core_proxy::CoreProxy;
|
||||
use crate::lsp::LspCatalog;
|
||||
use crate::plugin::PluginCatalog;
|
||||
use crate::terminal::{TermId, Terminal, TerminalEvent};
|
||||
use crate::terminal::{TermId, Terminal, TerminalHostEvent};
|
||||
use alacritty_terminal::ansi::CursorShape;
|
||||
use anyhow::{anyhow, Result};
|
||||
use crossbeam_channel::{unbounded, Receiver, Sender};
|
||||
use git2::{DiffOptions, Oid, Repository};
|
||||
|
@ -444,11 +445,20 @@ fn handle_notification(&self, rpc: Notification) {
|
|||
loop {
|
||||
let event = receiver.recv()?;
|
||||
match event {
|
||||
TerminalEvent::UpdateContent(content) => {
|
||||
TerminalHostEvent::UpdateContent { cursor, content } => {
|
||||
let shape = match cursor.shape {
|
||||
CursorShape::Block => "Block",
|
||||
CursorShape::Underline => "Underline",
|
||||
CursorShape::Beam => "Beam",
|
||||
CursorShape::HollowBlock => "HollowBlock",
|
||||
CursorShape::Hidden => "Hidden",
|
||||
};
|
||||
local_proxy.send_notification(
|
||||
"terminal_update_content",
|
||||
json!({
|
||||
"id": term_id,
|
||||
"cursor_shape": shape,
|
||||
"cursor_point": cursor.point,
|
||||
"content": content,
|
||||
}),
|
||||
);
|
||||
|
|
|
@ -8,13 +8,14 @@
|
|||
};
|
||||
|
||||
use alacritty_terminal::{
|
||||
ansi,
|
||||
config::Config,
|
||||
event::{Event, EventListener, Notify},
|
||||
event_loop::{EventLoop, Notifier},
|
||||
event::{Event, EventListener, Notify, OnResize},
|
||||
event_loop::{EventLoop, Msg, Notifier},
|
||||
grid::GridCell,
|
||||
index::Point,
|
||||
sync::FairMutex,
|
||||
term::{cell::Cell, SizeInfo},
|
||||
term::{cell::Cell, RenderableCursor, SizeInfo},
|
||||
tty, Term,
|
||||
};
|
||||
use anyhow::Result;
|
||||
|
@ -44,34 +45,42 @@ pub fn next() -> Self {
|
|||
}
|
||||
}
|
||||
|
||||
pub enum TerminalHostEvent {
|
||||
UpdateContent {
|
||||
cursor: RenderableCursor,
|
||||
content: Vec<(Point, Cell)>,
|
||||
},
|
||||
}
|
||||
|
||||
pub enum TerminalEvent {
|
||||
UpdateContent(Vec<(Point, Cell)>),
|
||||
resize(SizeInfo),
|
||||
event(Event),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Terminal {
|
||||
pub term: Arc<FairMutex<Term<EventProxy>>>,
|
||||
sender: Sender<Event>,
|
||||
host_sender: Sender<TerminalEvent>,
|
||||
sender: Sender<TerminalEvent>,
|
||||
host_sender: Sender<TerminalHostEvent>,
|
||||
}
|
||||
|
||||
pub type TermConfig = Config<HashMap<String, String>>;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct EventProxy {
|
||||
sender: Sender<Event>,
|
||||
sender: Sender<TerminalEvent>,
|
||||
}
|
||||
|
||||
impl EventProxy {}
|
||||
|
||||
impl EventListener for EventProxy {
|
||||
fn send_event(&self, event: alacritty_terminal::event::Event) {
|
||||
self.sender.send(event);
|
||||
self.sender.send(TerminalEvent::event(event));
|
||||
}
|
||||
}
|
||||
|
||||
impl Terminal {
|
||||
pub fn new(width: usize, height: usize) -> (Self, Receiver<TerminalEvent>) {
|
||||
pub fn new(width: usize, height: usize) -> (Self, Receiver<TerminalHostEvent>) {
|
||||
let config = TermConfig::default();
|
||||
let (sender, receiver) = crossbeam_channel::unbounded();
|
||||
let event_proxy = EventProxy {
|
||||
|
@ -99,24 +108,23 @@ pub fn new(width: usize, height: usize) -> (Self, Receiver<TerminalEvent>) {
|
|||
}
|
||||
|
||||
pub fn resize(&self, width: usize, height: usize) {
|
||||
self.term.lock().resize(SizeInfo::new(
|
||||
width as f32,
|
||||
height as f32,
|
||||
1.0,
|
||||
1.0,
|
||||
0.0,
|
||||
0.0,
|
||||
true,
|
||||
));
|
||||
let size =
|
||||
SizeInfo::new(width as f32, height as f32, 1.0, 1.0, 0.0, 0.0, true);
|
||||
self.sender.send(TerminalEvent::resize(size));
|
||||
self.term.lock().resize(size.clone());
|
||||
}
|
||||
|
||||
fn run(&self, receiver: Receiver<Event>, notifier: Notifier) {
|
||||
fn run(&self, receiver: Receiver<TerminalEvent>, mut notifier: Notifier) {
|
||||
let term = self.term.clone();
|
||||
let host_sender = self.host_sender.clone();
|
||||
std::thread::spawn(move || -> Result<()> {
|
||||
loop {
|
||||
let event = receiver.recv()?;
|
||||
match event {
|
||||
TerminalEvent::resize(size) => {
|
||||
notifier.on_resize(&size);
|
||||
}
|
||||
TerminalEvent::event(event) => match event {
|
||||
Event::MouseCursorDirty => {}
|
||||
Event::Title(_) => {}
|
||||
Event::ResetTitle => {}
|
||||
|
@ -124,34 +132,45 @@ fn run(&self, receiver: Receiver<Event>, notifier: Notifier) {
|
|||
Event::ClipboardLoad(_, _) => {}
|
||||
Event::ColorRequest(_, _) => {}
|
||||
Event::PtyWrite(s) => {
|
||||
eprintln!("pty write {}", s);
|
||||
notifier.notify(s.into_bytes());
|
||||
}
|
||||
Event::CursorBlinkingChange(_) => {}
|
||||
Event::Wakeup => {
|
||||
let cursor =
|
||||
term.lock().renderable_content().cursor.clone();
|
||||
let content = term
|
||||
.lock()
|
||||
.renderable_content()
|
||||
.display_iter
|
||||
.filter_map(|c| {
|
||||
if c.is_empty() {
|
||||
if (c.c == ' ' || c.c == '\t')
|
||||
&& c.bg
|
||||
== ansi::Color::Named(
|
||||
ansi::NamedColor::Background,
|
||||
)
|
||||
{
|
||||
None
|
||||
} else {
|
||||
Some((c.point, c.cell.clone()))
|
||||
}
|
||||
})
|
||||
.collect::<Vec<(Point, Cell)>>();
|
||||
let event = TerminalEvent::UpdateContent(content);
|
||||
let event = TerminalHostEvent::UpdateContent {
|
||||
content: content,
|
||||
cursor: cursor,
|
||||
};
|
||||
host_sender.send(event);
|
||||
}
|
||||
Event::Bell => {}
|
||||
Event::Exit => {}
|
||||
},
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pub fn insert<B: Into<String>>(&self, data: B) {
|
||||
self.sender.send(Event::PtyWrite(data.into()));
|
||||
self.sender
|
||||
.send(TerminalEvent::event(Event::PtyWrite(data.into())));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue