mirror of
https://github.com/zed-industries/zed.git
synced 2024-11-09 21:26:14 +03:00
More compilation fixes
This commit is contained in:
parent
61d6cb880c
commit
a238368296
@ -1,4 +1,4 @@
|
||||
use gpui::{AppContext, FontFeatures};
|
||||
use gpui::{AppContext, FontFeatures, Pixels};
|
||||
use schemars::JsonSchema;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::{collections::HashMap, path::PathBuf};
|
||||
@ -15,7 +15,7 @@ pub enum TerminalDockPosition {
|
||||
pub struct TerminalSettings {
|
||||
pub shell: Shell,
|
||||
pub working_directory: WorkingDirectory,
|
||||
font_size: Option<f32>,
|
||||
pub font_size: Option<Pixels>,
|
||||
pub font_family: Option<String>,
|
||||
pub line_height: TerminalLineHeight,
|
||||
pub font_features: Option<FontFeatures>,
|
||||
@ -90,14 +90,6 @@ pub struct TerminalSettingsContent {
|
||||
pub detect_venv: Option<VenvSettings>,
|
||||
}
|
||||
|
||||
impl TerminalSettings {
|
||||
// todo!("move to terminal element")
|
||||
// pub fn font_size(&self, cx: &AppContext) -> Option<f32> {
|
||||
// self.font_size
|
||||
// .map(|size| theme2::adjusted_font_size(size, cx))
|
||||
// }
|
||||
}
|
||||
|
||||
impl settings::Settings for TerminalSettings {
|
||||
const KEY: Option<&'static str> = Some("terminal");
|
||||
|
||||
|
@ -1,11 +1,13 @@
|
||||
use editor::{Cursor, HighlightedRange, HighlightedRangeLine};
|
||||
use gpui::{
|
||||
serde_json::json, AnyElement, Bounds, HighlightStyle, Hsla, Line, ModelContext, MouseButton,
|
||||
Pixels, Point, TextStyle, ViewContext, WeakModel, WindowContext,
|
||||
AnyElement, AppContext, Bounds, Component, Element, HighlightStyle, Hsla, LayoutId, Line,
|
||||
ModelContext, MouseButton, Pixels, Point, TextStyle, Underline, ViewContext, WeakModel,
|
||||
WindowContext,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use language::CursorShape;
|
||||
use ordered_float::OrderedFloat;
|
||||
use settings::Settings;
|
||||
use terminal::{
|
||||
alacritty_terminal::{
|
||||
ansi::{Color as AnsiColor, Color::Named, CursorShape as AlacCursorShape, NamedColor},
|
||||
@ -21,10 +23,9 @@ use terminal::{
|
||||
TerminalSize,
|
||||
};
|
||||
use theme::ThemeSettings;
|
||||
use util::ResultExt;
|
||||
|
||||
use std::mem;
|
||||
use std::{fmt::Debug, ops::RangeInclusive};
|
||||
use std::{mem, ops::Range};
|
||||
|
||||
use crate::TerminalView;
|
||||
|
||||
@ -143,7 +144,7 @@ impl LayoutRect {
|
||||
cx.paint_quad(
|
||||
Bounds::new(position, size),
|
||||
Default::default(),
|
||||
Some(self.color),
|
||||
self.color,
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
);
|
||||
@ -282,10 +283,10 @@ impl TerminalElement {
|
||||
text_fragment: &Line,
|
||||
) -> Option<(Vector2F, f32)> {
|
||||
if cursor_point.line() < size.total_lines() as i32 {
|
||||
let cursor_width = if text_fragment.width() == 0. {
|
||||
let cursor_width = if text_fragment.width == 0. {
|
||||
size.cell_width()
|
||||
} else {
|
||||
text_fragment.width()
|
||||
text_fragment.width
|
||||
};
|
||||
|
||||
//Cursor should always surround as much of the text as possible,
|
||||
@ -339,7 +340,7 @@ impl TerminalElement {
|
||||
|
||||
let font_id = font_cache
|
||||
.select_font(text_style.font_family_id, &properties)
|
||||
.unwrap_or(text_style.font_id);
|
||||
.unwrap_or(8text_style.font_id);
|
||||
|
||||
let mut result = RunStyle {
|
||||
color: fg,
|
||||
@ -369,7 +370,7 @@ impl TerminalElement {
|
||||
) -> impl Fn(E, &mut TerminalView, &mut EventContext<TerminalView>) {
|
||||
move |event, _: &mut TerminalView, cx| {
|
||||
cx.focus_parent();
|
||||
if let Some(conn_handle) = connection.upgrade(cx) {
|
||||
if let Some(conn_handle) = connection.upgrade() {
|
||||
conn_handle.update(cx, |terminal, cx| {
|
||||
f(terminal, origin, event, cx);
|
||||
|
||||
@ -382,7 +383,7 @@ impl TerminalElement {
|
||||
fn attach_mouse_handlers(
|
||||
&self,
|
||||
origin: Point<Pixels>,
|
||||
visible_bounds: Bounds,
|
||||
visible_bounds: Bounds<Pixels>,
|
||||
mode: TermMode,
|
||||
cx: &mut ViewContext<TerminalView>,
|
||||
) {
|
||||
@ -397,7 +398,7 @@ impl TerminalElement {
|
||||
let terminal_view = cx.handle();
|
||||
cx.focus(&terminal_view);
|
||||
v.context_menu.update(cx, |menu, _cx| menu.delay_cancel());
|
||||
if let Some(conn_handle) = connection.upgrade(cx) {
|
||||
if let Some(conn_handle) = connection.upgrade() {
|
||||
conn_handle.update(cx, |terminal, cx| {
|
||||
terminal.mouse_down(&event, origin);
|
||||
|
||||
@ -412,7 +413,7 @@ impl TerminalElement {
|
||||
}
|
||||
|
||||
if cx.is_self_focused() {
|
||||
if let Some(conn_handle) = connection.upgrade(cx) {
|
||||
if let Some(conn_handle) = connection.upgrade() {
|
||||
conn_handle.update(cx, |terminal, cx| {
|
||||
terminal.mouse_drag(event, origin);
|
||||
cx.notify();
|
||||
@ -435,7 +436,7 @@ impl TerminalElement {
|
||||
.on_click(
|
||||
MouseButton::Right,
|
||||
move |event, view: &mut TerminalView, cx| {
|
||||
let mouse_mode = if let Some(conn_handle) = connection.upgrade(cx) {
|
||||
let mouse_mode = if let Some(conn_handle) = connection.upgrade() {
|
||||
conn_handle.update(cx, |terminal, _cx| terminal.mouse_mode(event.shift))
|
||||
} else {
|
||||
// If we can't get the model handle, probably can't deploy the context menu
|
||||
@ -448,7 +449,7 @@ impl TerminalElement {
|
||||
)
|
||||
.on_move(move |event, _: &mut TerminalView, cx| {
|
||||
if cx.is_self_focused() {
|
||||
if let Some(conn_handle) = connection.upgrade(cx) {
|
||||
if let Some(conn_handle) = connection.upgrade() {
|
||||
conn_handle.update(cx, |terminal, cx| {
|
||||
terminal.mouse_move(&event, origin);
|
||||
cx.notify();
|
||||
@ -457,7 +458,7 @@ impl TerminalElement {
|
||||
}
|
||||
})
|
||||
.on_scroll(move |event, _: &mut TerminalView, cx| {
|
||||
if let Some(conn_handle) = connection.upgrade(cx) {
|
||||
if let Some(conn_handle) = connection.upgrade() {
|
||||
conn_handle.update(cx, |terminal, cx| {
|
||||
terminal.scroll_wheel(event, origin);
|
||||
cx.notify();
|
||||
@ -516,17 +517,16 @@ impl TerminalElement {
|
||||
}
|
||||
|
||||
impl Element<TerminalView> for TerminalElement {
|
||||
type LayoutState = LayoutState;
|
||||
type PaintState = ();
|
||||
type ElementState = LayoutState;
|
||||
|
||||
fn layout(
|
||||
&mut self,
|
||||
constraint: gpui::SizeConstraint,
|
||||
view: &mut TerminalView,
|
||||
view_state: &mut TerminalView,
|
||||
element_state: &mut Self::ElementState,
|
||||
cx: &mut ViewContext<TerminalView>,
|
||||
) -> (gpui::geometry::vector::Vector2F, Self::LayoutState) {
|
||||
let settings = settings::get::<ThemeSettings>(cx);
|
||||
let terminal_settings = settings::get::<TerminalSettings>(cx);
|
||||
) -> LayoutId {
|
||||
let settings = ThemeSettings::get_global(cx);
|
||||
let terminal_settings = TerminalSettings::get_global(cx);
|
||||
|
||||
//Setup layout information
|
||||
let terminal_theme = settings.theme.terminal.clone(); //TODO: Try to minimize this clone.
|
||||
@ -534,9 +534,7 @@ impl Element<TerminalView> for TerminalElement {
|
||||
let tooltip_style = settings.theme.tooltip.clone();
|
||||
|
||||
let font_cache = cx.font_cache();
|
||||
let font_size = terminal_settings
|
||||
.font_size(cx)
|
||||
.unwrap_or(settings.buffer_font_size(cx));
|
||||
let font_size = font_size(&terminal_settings, cx).unwrap_or(settings.buffer_font_size(cx));
|
||||
let font_family_name = terminal_settings
|
||||
.font_family
|
||||
.as_ref()
|
||||
@ -575,14 +573,14 @@ impl Element<TerminalView> for TerminalElement {
|
||||
TerminalSize::new(line_height, cell_width, size)
|
||||
};
|
||||
|
||||
let search_matches = if let Some(terminal_model) = self.terminal.upgrade(cx) {
|
||||
let search_matches = if let Some(terminal_model) = self.terminal.upgrade() {
|
||||
terminal_model.read(cx).matches.clone()
|
||||
} else {
|
||||
Default::default()
|
||||
};
|
||||
|
||||
let background_color = terminal_theme.background;
|
||||
let terminal_handle = self.terminal.upgrade(cx).unwrap();
|
||||
let terminal_handle = self.terminal.upgrade().unwrap();
|
||||
|
||||
let last_hovered_word = terminal_handle.update(cx, |terminal, cx| {
|
||||
terminal.set_size(dimensions);
|
||||
@ -614,7 +612,7 @@ impl Element<TerminalView> for TerminalElement {
|
||||
|
||||
tooltip.layout(
|
||||
SizeConstraint::new(Vector2F::zero(), cx.window_size()),
|
||||
view,
|
||||
view_state,
|
||||
cx,
|
||||
);
|
||||
tooltip
|
||||
@ -709,7 +707,7 @@ impl Element<TerminalView> for TerminalElement {
|
||||
//Done!
|
||||
(
|
||||
constraint.max,
|
||||
LayoutState {
|
||||
Self::ElementState {
|
||||
cells,
|
||||
cursor,
|
||||
background_color,
|
||||
@ -726,26 +724,25 @@ impl Element<TerminalView> for TerminalElement {
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
bounds: Bounds,
|
||||
visible_bounds: Bounds,
|
||||
layout: &mut Self::LayoutState,
|
||||
view: &mut TerminalView,
|
||||
bounds: Bounds<Pixels>,
|
||||
view_state: &mut TerminalView,
|
||||
element_state: &mut Self::ElementState,
|
||||
cx: &mut ViewContext<TerminalView>,
|
||||
) -> Self::PaintState {
|
||||
) {
|
||||
let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default();
|
||||
|
||||
//Setup element stuff
|
||||
let clip_bounds = Some(visible_bounds);
|
||||
|
||||
cx.paint_layer(clip_bounds, |cx| {
|
||||
let origin = bounds.origin() + vec2f(layout.gutter, 0.);
|
||||
let origin = bounds.origin() + vec2f(element_state.gutter, 0.);
|
||||
|
||||
// Elements are ephemeral, only at paint time do we know what could be clicked by a mouse
|
||||
self.attach_mouse_handlers(origin, visible_bounds, layout.mode, cx);
|
||||
self.attach_mouse_handlers(origin, visible_bounds, element_state.mode, cx);
|
||||
|
||||
cx.scene().push_cursor_region(gpui::CursorRegion {
|
||||
bounds,
|
||||
style: if layout.hyperlink_tooltip.is_some() {
|
||||
style: if element_state.hyperlink_tooltip.is_some() {
|
||||
CursorStyle::AlacPointingHand
|
||||
} else {
|
||||
CursorStyle::IBeam
|
||||
@ -755,31 +752,34 @@ impl Element<TerminalView> for TerminalElement {
|
||||
cx.paint_layer(clip_bounds, |cx| {
|
||||
//Start with a background color
|
||||
cx.scene().push_quad(Quad {
|
||||
bounds: RectF::new(bounds.origin(), bounds.size()),
|
||||
background: Some(layout.background_color),
|
||||
bounds,
|
||||
background: Some(element_state.background_color),
|
||||
border: Default::default(),
|
||||
corner_radii: Default::default(),
|
||||
});
|
||||
|
||||
for rect in &layout.rects {
|
||||
rect.paint(origin, layout, view, cx);
|
||||
for rect in &element_state.rects {
|
||||
rect.paint(origin, element_state, view_state, cx);
|
||||
}
|
||||
});
|
||||
|
||||
//Draw Highlighted Backgrounds
|
||||
cx.paint_layer(clip_bounds, |cx| {
|
||||
for (relative_highlighted_range, color) in layout.relative_highlighted_ranges.iter()
|
||||
for (relative_highlighted_range, color) in
|
||||
element_state.relative_highlighted_ranges.iter()
|
||||
{
|
||||
if let Some((start_y, highlighted_range_lines)) =
|
||||
to_highlighted_range_lines(relative_highlighted_range, layout, origin)
|
||||
{
|
||||
if let Some((start_y, highlighted_range_lines)) = to_highlighted_range_lines(
|
||||
relative_highlighted_range,
|
||||
element_state,
|
||||
origin,
|
||||
) {
|
||||
let hr = HighlightedRange {
|
||||
start_y, //Need to change this
|
||||
line_height: layout.size.line_height,
|
||||
line_height: element_state.size.line_height,
|
||||
lines: highlighted_range_lines,
|
||||
color: color.clone(),
|
||||
//Copied from editor. TODO: move to theme or something
|
||||
corner_radius: 0.15 * layout.size.line_height,
|
||||
corner_radius: 0.15 * element_state.size.line_height,
|
||||
};
|
||||
hr.paint(bounds, cx);
|
||||
}
|
||||
@ -788,63 +788,83 @@ impl Element<TerminalView> for TerminalElement {
|
||||
|
||||
//Draw the text cells
|
||||
cx.paint_layer(clip_bounds, |cx| {
|
||||
for cell in &layout.cells {
|
||||
cell.paint(origin, layout, visible_bounds, view, cx);
|
||||
for cell in &element_state.cells {
|
||||
cell.paint(origin, element_state, visible_bounds, view_state, cx);
|
||||
}
|
||||
});
|
||||
|
||||
//Draw cursor
|
||||
if self.cursor_visible {
|
||||
if let Some(cursor) = &layout.cursor {
|
||||
if let Some(cursor) = &element_state.cursor {
|
||||
cx.paint_layer(clip_bounds, |cx| {
|
||||
cursor.paint(origin, cx);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(element) = &mut layout.hyperlink_tooltip {
|
||||
element.paint(origin, visible_bounds, view, cx)
|
||||
if let Some(element) = &mut element_state.hyperlink_tooltip {
|
||||
element.paint(origin, visible_bounds, view_state, cx)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Option<&dyn std::any::Any> {
|
||||
None
|
||||
fn id(&self) -> Option<gpui::ElementId> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn debug(
|
||||
&self,
|
||||
_: Bounds,
|
||||
_: &Self::LayoutState,
|
||||
_: &Self::PaintState,
|
||||
_: &TerminalView,
|
||||
_: &gpui::ViewContext<TerminalView>,
|
||||
) -> gpui::serde_json::Value {
|
||||
json!({
|
||||
"type": "TerminalElement",
|
||||
})
|
||||
fn initialize(
|
||||
&mut self,
|
||||
view_state: &mut TerminalView,
|
||||
element_state: Option<Self::ElementState>,
|
||||
cx: &mut ViewContext<TerminalView>,
|
||||
) -> Self::ElementState {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn rect_for_text_range(
|
||||
&self,
|
||||
_: Range<usize>,
|
||||
bounds: Bounds,
|
||||
_: Bounds,
|
||||
layout: &Self::LayoutState,
|
||||
_: &Self::PaintState,
|
||||
_: &TerminalView,
|
||||
_: &gpui::ViewContext<TerminalView>,
|
||||
) -> Option<RectF> {
|
||||
// Use the same origin that's passed to `Cursor::paint` in the paint
|
||||
// method bove.
|
||||
let mut origin = bounds.origin() + vec2f(layout.size.cell_width, 0.);
|
||||
// todo!() remove?
|
||||
// fn metadata(&self) -> Option<&dyn std::any::Any> {
|
||||
// None
|
||||
// }
|
||||
|
||||
// TODO - Why is it necessary to move downward one line to get correct
|
||||
// positioning? I would think that we'd want the same rect that is
|
||||
// painted for the cursor.
|
||||
origin += vec2f(0., layout.size.line_height);
|
||||
// fn debug(
|
||||
// &self,
|
||||
// _: Bounds<Pixels>,
|
||||
// _: &Self::ElementState,
|
||||
// _: &Self::PaintState,
|
||||
// _: &TerminalView,
|
||||
// _: &gpui::ViewContext<TerminalView>,
|
||||
// ) -> gpui::serde_json::Value {
|
||||
// json!({
|
||||
// "type": "TerminalElement",
|
||||
// })
|
||||
// }
|
||||
|
||||
Some(layout.cursor.as_ref()?.bounding_rect(origin))
|
||||
// fn rect_for_text_range(
|
||||
// &self,
|
||||
// _: Range<usize>,
|
||||
// bounds: Bounds<Pixels>,
|
||||
// _: Bounds<Pixels>,
|
||||
// layout: &Self::ElementState,
|
||||
// _: &Self::PaintState,
|
||||
// _: &TerminalView,
|
||||
// _: &gpui::ViewContext<TerminalView>,
|
||||
// ) -> Option<Bounds<Pixels>> {
|
||||
// // Use the same origin that's passed to `Cursor::paint` in the paint
|
||||
// // method bove.
|
||||
// let mut origin = bounds.origin() + vec2f(layout.size.cell_width, 0.);
|
||||
|
||||
// // TODO - Why is it necessary to move downward one line to get correct
|
||||
// // positioning? I would think that we'd want the same rect that is
|
||||
// // painted for the cursor.
|
||||
// origin += vec2f(0., layout.size.line_height);
|
||||
|
||||
// Some(layout.cursor.as_ref()?.bounding_rect(origin))
|
||||
// }
|
||||
}
|
||||
|
||||
impl Component<TerminalView> for TerminalElement {
|
||||
fn render(self) -> AnyElement<TerminalView> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
@ -933,3 +953,9 @@ fn to_highlighted_range_lines(
|
||||
|
||||
Some((start_y, highlighted_range_lines))
|
||||
}
|
||||
|
||||
fn font_size(terminal_settings: &TerminalSettings, cx: &mut AppContext) -> Option<Pixels> {
|
||||
terminal_settings
|
||||
.font_size
|
||||
.map(|size| theme::adjusted_font_size(size, cx))
|
||||
}
|
||||
|
@ -3,27 +3,34 @@ use std::{path::PathBuf, sync::Arc};
|
||||
use crate::TerminalView;
|
||||
use db::kvp::KEY_VALUE_STORE;
|
||||
use gpui::{
|
||||
actions, anyhow::Result, elements::*, serde_json, Action, AppContext, AsyncAppContext, Entity,
|
||||
Subscription, Task, View, ViewContext, ViewHandle, WeakViewHandle, WindowContext,
|
||||
actions, serde_json, Action, AppContext, AsyncAppContext, Entity, EventEmitter, Render,
|
||||
Subscription, Task, View, ViewContext, VisualContext, WeakView, WindowContext,
|
||||
};
|
||||
use project::Fs;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use settings::SettingsStore;
|
||||
use settings::{Settings, SettingsStore};
|
||||
use terminal::terminal_settings::{TerminalDockPosition, TerminalSettings};
|
||||
use util::{ResultExt, TryFutureExt};
|
||||
use workspace::{
|
||||
dock::{DockPosition, Panel},
|
||||
dock::{DockPosition, Panel, PanelEvent},
|
||||
item::Item,
|
||||
pane, DraggedItem, Pane, Workspace,
|
||||
pane, Pane, Workspace,
|
||||
};
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
const TERMINAL_PANEL_KEY: &'static str = "TerminalPanel";
|
||||
|
||||
actions!(terminal_panel, [ToggleFocus]);
|
||||
actions!(ToggleFocus);
|
||||
|
||||
pub fn init(cx: &mut AppContext) {
|
||||
cx.add_action(TerminalPanel::new_terminal);
|
||||
cx.add_action(TerminalPanel::open_terminal);
|
||||
cx.observe_new_views(
|
||||
|workspace: &mut Workspace, _: &mut ViewContext<Workspace>| {
|
||||
workspace.register_action(TerminalPanel::new_terminal);
|
||||
workspace.register_action(TerminalPanel::open_terminal);
|
||||
},
|
||||
)
|
||||
.detach();
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -36,9 +43,9 @@ pub enum Event {
|
||||
}
|
||||
|
||||
pub struct TerminalPanel {
|
||||
pane: ViewHandle<Pane>,
|
||||
pane: View<Pane>,
|
||||
fs: Arc<dyn Fs>,
|
||||
workspace: WeakViewHandle<Workspace>,
|
||||
workspace: WeakView<Workspace>,
|
||||
width: Option<f32>,
|
||||
height: Option<f32>,
|
||||
pending_serialization: Task<Option<()>>,
|
||||
@ -48,12 +55,11 @@ pub struct TerminalPanel {
|
||||
impl TerminalPanel {
|
||||
fn new(workspace: &Workspace, cx: &mut ViewContext<Self>) -> Self {
|
||||
let weak_self = cx.weak_handle();
|
||||
let pane = cx.add_view(|cx| {
|
||||
let window = cx.window();
|
||||
let pane = cx.build_view(|cx| {
|
||||
let window = cx.window_handle();
|
||||
let mut pane = Pane::new(
|
||||
workspace.weak_handle(),
|
||||
workspace.project().clone(),
|
||||
workspace.app_state().background_actions,
|
||||
Default::default(),
|
||||
cx,
|
||||
);
|
||||
@ -78,7 +84,7 @@ impl TerminalPanel {
|
||||
move |_, cx| {
|
||||
let this = this.clone();
|
||||
cx.window_context().defer(move |cx| {
|
||||
if let Some(this) = this.upgrade(cx) {
|
||||
if let Some(this) = this.upgrade() {
|
||||
this.update(cx, |this, cx| {
|
||||
this.add_terminal(None, cx);
|
||||
});
|
||||
@ -104,7 +110,7 @@ impl TerminalPanel {
|
||||
))
|
||||
.into_any()
|
||||
});
|
||||
let buffer_search_bar = cx.add_view(search::BufferSearchBar::new);
|
||||
let buffer_search_bar = cx.build_view(search::BufferSearchBar::new);
|
||||
pane.toolbar()
|
||||
.update(cx, |toolbar, cx| toolbar.add_item(buffer_search_bar, cx));
|
||||
pane
|
||||
@ -123,7 +129,7 @@ impl TerminalPanel {
|
||||
_subscriptions: subscriptions,
|
||||
};
|
||||
let mut old_dock_position = this.position(cx);
|
||||
cx.observe_global::<SettingsStore, _>(move |this, cx| {
|
||||
cx.observe_global::<SettingsStore>(move |this, cx| {
|
||||
let new_dock_position = this.position(cx);
|
||||
if new_dock_position != old_dock_position {
|
||||
old_dock_position = new_dock_position;
|
||||
@ -134,13 +140,10 @@ impl TerminalPanel {
|
||||
this
|
||||
}
|
||||
|
||||
pub fn load(
|
||||
workspace: WeakViewHandle<Workspace>,
|
||||
cx: AsyncAppContext,
|
||||
) -> Task<Result<ViewHandle<Self>>> {
|
||||
pub fn load(workspace: WeakView<Workspace>, cx: AsyncAppContext) -> Task<Result<View<Self>>> {
|
||||
cx.spawn(|mut cx| async move {
|
||||
let serialized_panel = if let Some(panel) = cx
|
||||
.background()
|
||||
.background_executor()
|
||||
.spawn(async move { KEY_VALUE_STORE.read_kvp(TERMINAL_PANEL_KEY) })
|
||||
.await
|
||||
.log_err()
|
||||
@ -151,7 +154,7 @@ impl TerminalPanel {
|
||||
None
|
||||
};
|
||||
let (panel, pane, items) = workspace.update(&mut cx, |workspace, cx| {
|
||||
let panel = cx.add_view(|cx| TerminalPanel::new(workspace, cx));
|
||||
let panel = cx.build_view(|cx| TerminalPanel::new(workspace, cx));
|
||||
let items = if let Some(serialized_panel) = serialized_panel.as_ref() {
|
||||
panel.update(cx, |panel, cx| {
|
||||
cx.notify();
|
||||
@ -189,7 +192,7 @@ impl TerminalPanel {
|
||||
let mut active_ix = None;
|
||||
for item in items {
|
||||
if let Some(item) = item.log_err() {
|
||||
let item_id = item.id();
|
||||
let item_id = item.entity_id().as_u64();
|
||||
pane.add_item(Box::new(item), false, false, None, cx);
|
||||
if Some(item_id) == active_item_id {
|
||||
active_ix = Some(pane.items_len() - 1);
|
||||
@ -208,7 +211,7 @@ impl TerminalPanel {
|
||||
|
||||
fn handle_pane_event(
|
||||
&mut self,
|
||||
_pane: ViewHandle<Pane>,
|
||||
_pane: View<Pane>,
|
||||
event: &pane::Event,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
@ -221,7 +224,7 @@ impl TerminalPanel {
|
||||
pane::Event::Focus => cx.emit(Event::Focus),
|
||||
|
||||
pane::Event::AddItem { item } => {
|
||||
if let Some(workspace) = self.workspace.upgrade(cx) {
|
||||
if let Some(workspace) = self.workspace.upgrade() {
|
||||
let pane = self.pane.clone();
|
||||
workspace.update(cx, |workspace, cx| item.added_to_pane(workspace, pane, cx))
|
||||
}
|
||||
@ -261,24 +264,23 @@ impl TerminalPanel {
|
||||
fn add_terminal(&mut self, working_directory: Option<PathBuf>, cx: &mut ViewContext<Self>) {
|
||||
let workspace = self.workspace.clone();
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
let pane = this.read_with(&cx, |this, _| this.pane.clone())?;
|
||||
let pane = this.update(&mut cx, |this, _| this.pane.clone())?;
|
||||
workspace.update(&mut cx, |workspace, cx| {
|
||||
let working_directory = if let Some(working_directory) = working_directory {
|
||||
Some(working_directory)
|
||||
} else {
|
||||
let working_directory_strategy = settings::get::<TerminalSettings>(cx)
|
||||
.working_directory
|
||||
.clone();
|
||||
let working_directory_strategy =
|
||||
TerminalSettings::get_global(cx).working_directory.clone();
|
||||
crate::get_working_directory(workspace, cx, working_directory_strategy)
|
||||
};
|
||||
|
||||
let window = cx.window();
|
||||
let window = cx.window_handle();
|
||||
if let Some(terminal) = workspace.project().update(cx, |project, cx| {
|
||||
project
|
||||
.create_terminal(working_directory, window, cx)
|
||||
.log_err()
|
||||
}) {
|
||||
let terminal = Box::new(cx.add_view(|cx| {
|
||||
let terminal = Box::new(cx.build_view(|cx| {
|
||||
TerminalView::new(
|
||||
terminal,
|
||||
workspace.weak_handle(),
|
||||
@ -287,7 +289,7 @@ impl TerminalPanel {
|
||||
)
|
||||
}));
|
||||
pane.update(cx, |pane, cx| {
|
||||
let focus = pane.has_focus();
|
||||
let focus = pane.has_focus(cx);
|
||||
pane.add_item(terminal, true, focus, None, cx);
|
||||
});
|
||||
}
|
||||
@ -303,12 +305,16 @@ impl TerminalPanel {
|
||||
.pane
|
||||
.read(cx)
|
||||
.items()
|
||||
.map(|item| item.id())
|
||||
.map(|item| item.id().as_u64())
|
||||
.collect::<Vec<_>>();
|
||||
let active_item_id = self.pane.read(cx).active_item().map(|item| item.id());
|
||||
let active_item_id = self
|
||||
.pane
|
||||
.read(cx)
|
||||
.active_item()
|
||||
.map(|item| item.id().as_u64());
|
||||
let height = self.height;
|
||||
let width = self.width;
|
||||
self.pending_serialization = cx.background().spawn(
|
||||
self.pending_serialization = cx.background_executor().spawn(
|
||||
async move {
|
||||
KEY_VALUE_STORE
|
||||
.write_kvp(
|
||||
@ -328,29 +334,25 @@ impl TerminalPanel {
|
||||
}
|
||||
}
|
||||
|
||||
impl Entity for TerminalPanel {
|
||||
type Event = Event;
|
||||
}
|
||||
|
||||
impl View for TerminalPanel {
|
||||
fn ui_name() -> &'static str {
|
||||
"TerminalPanel"
|
||||
}
|
||||
impl EventEmitter<Event> for TerminalPanel {}
|
||||
impl EventEmitter<PanelEvent> for TerminalPanel {}
|
||||
|
||||
impl Render for TerminalPanel {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> gpui::AnyElement<Self> {
|
||||
ChildView::new(&self.pane, cx).into_any()
|
||||
}
|
||||
|
||||
fn focus_in(&mut self, _: gpui::AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||
if cx.is_self_focused() {
|
||||
cx.focus(&self.pane);
|
||||
}
|
||||
}
|
||||
// todo!()
|
||||
// fn focus_in(&mut self, _: gpui::AnyView, cx: &mut ViewContext<Self>) {
|
||||
// if cx.is_self_focused() {
|
||||
// cx.focus(&self.pane);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
impl Panel for TerminalPanel {
|
||||
fn position(&self, cx: &WindowContext) -> DockPosition {
|
||||
match settings::get::<TerminalSettings>(cx).dock {
|
||||
match TerminalSettings::get_global(cx).dock {
|
||||
TerminalDockPosition::Left => DockPosition::Left,
|
||||
TerminalDockPosition::Bottom => DockPosition::Bottom,
|
||||
TerminalDockPosition::Right => DockPosition::Right,
|
||||
@ -373,7 +375,7 @@ impl Panel for TerminalPanel {
|
||||
}
|
||||
|
||||
fn size(&self, cx: &WindowContext) -> f32 {
|
||||
let settings = settings::get::<TerminalSettings>(cx);
|
||||
let settings = TerminalSettings::get_global(cx);
|
||||
match self.position(cx) {
|
||||
DockPosition::Left | DockPosition::Right => {
|
||||
self.width.unwrap_or_else(|| settings.default_width)
|
||||
@ -391,14 +393,6 @@ impl Panel for TerminalPanel {
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn should_zoom_in_on_event(event: &Event) -> bool {
|
||||
matches!(event, Event::ZoomIn)
|
||||
}
|
||||
|
||||
fn should_zoom_out_on_event(event: &Event) -> bool {
|
||||
matches!(event, Event::ZoomOut)
|
||||
}
|
||||
|
||||
fn is_zoomed(&self, cx: &WindowContext) -> bool {
|
||||
self.pane.read(cx).is_zoomed()
|
||||
}
|
||||
@ -430,31 +424,44 @@ impl Panel for TerminalPanel {
|
||||
}
|
||||
}
|
||||
|
||||
fn should_change_position_on_event(event: &Self::Event) -> bool {
|
||||
matches!(event, Event::DockPositionChanged)
|
||||
}
|
||||
|
||||
fn should_activate_on_event(_: &Self::Event) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn should_close_on_event(event: &Event) -> bool {
|
||||
matches!(event, Event::Close)
|
||||
}
|
||||
|
||||
fn has_focus(&self, cx: &WindowContext) -> bool {
|
||||
self.pane.read(cx).has_focus()
|
||||
self.pane.read(cx).has_focus(cx)
|
||||
}
|
||||
|
||||
fn is_focus_event(event: &Self::Event) -> bool {
|
||||
matches!(event, Event::Focus)
|
||||
fn persistent_name(&self) -> &'static str {
|
||||
todo!()
|
||||
}
|
||||
|
||||
// todo!() is it needed?
|
||||
// fn should_change_position_on_event(event: &Self::Event) -> bool {
|
||||
// matches!(event, Event::DockPositionChanged)
|
||||
// }
|
||||
|
||||
// fn should_activate_on_event(_: &Self::Event) -> bool {
|
||||
// false
|
||||
// }
|
||||
|
||||
// fn should_close_on_event(event: &Event) -> bool {
|
||||
// matches!(event, Event::Close)
|
||||
// }
|
||||
|
||||
// fn is_focus_event(event: &Self::Event) -> bool {
|
||||
// matches!(event, Event::Focus)
|
||||
// }
|
||||
|
||||
// fn should_zoom_in_on_event(event: &Event) -> bool {
|
||||
// matches!(event, Event::ZoomIn)
|
||||
// }
|
||||
|
||||
// fn should_zoom_out_on_event(event: &Event) -> bool {
|
||||
// matches!(event, Event::ZoomOut)
|
||||
// }
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct SerializedTerminalPanel {
|
||||
items: Vec<usize>,
|
||||
active_item_id: Option<usize>,
|
||||
items: Vec<u64>,
|
||||
active_item_id: Option<u64>,
|
||||
width: Option<f32>,
|
||||
height: Option<f32>,
|
||||
}
|
||||
|
@ -10,10 +10,11 @@ use anyhow::Context;
|
||||
use dirs::home_dir;
|
||||
use editor::{scroll::autoscroll::Autoscroll, Editor};
|
||||
use gpui::{
|
||||
actions, div, img, red, register_action, AnyElement, AppContext, Component, Div, EventEmitter,
|
||||
FocusEvent, FocusHandle, Focusable, FocusableKeyDispatch, InputHandler, KeyDownEvent,
|
||||
Keystroke, Model, ParentElement, Pixels, Render, StatefulInteractivity, StatelessInteractive,
|
||||
Styled, Task, View, ViewContext, VisualContext, WeakView,
|
||||
actions, div, img, red, register_action, AnyElement, AppContext, Component, DispatchPhase, Div,
|
||||
EventEmitter, FocusEvent, FocusHandle, Focusable, FocusableKeyDispatch, InputHandler,
|
||||
KeyDownEvent, Keystroke, Model, ParentElement, Pixels, Render, SharedString,
|
||||
StatefulInteractivity, StatelessInteractive, Styled, Task, View, ViewContext, VisualContext,
|
||||
WeakView,
|
||||
};
|
||||
use language::Bias;
|
||||
use project::{search::SearchQuery, LocalWorktree, Project};
|
||||
@ -21,7 +22,6 @@ use serde::Deserialize;
|
||||
use settings::Settings;
|
||||
use smol::Timer;
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
ops::RangeInclusive,
|
||||
path::{Path, PathBuf},
|
||||
sync::Arc,
|
||||
@ -40,7 +40,7 @@ use workspace::{
|
||||
item::{BreadcrumbText, Item, ItemEvent},
|
||||
notifications::NotifyResultExt,
|
||||
register_deserializable_item,
|
||||
searchable::{SearchEvent, SearchOptions, SearchableItem, SearchableItemHandle},
|
||||
searchable::{SearchEvent, SearchOptions, SearchableItem},
|
||||
NewCenterTerminal, Pane, ToolbarItemLocation, Workspace, WorkspaceId,
|
||||
};
|
||||
|
||||
@ -51,11 +51,11 @@ const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
|
||||
pub struct ScrollTerminal(pub i32);
|
||||
|
||||
#[register_action]
|
||||
#[derive(Clone, Default, Deserialize, PartialEq)]
|
||||
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
|
||||
pub struct SendText(String);
|
||||
|
||||
#[register_action]
|
||||
#[derive(Clone, Default, Deserialize, PartialEq)]
|
||||
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
|
||||
pub struct SendKeystroke(String);
|
||||
|
||||
actions!(Clear, Copy, Paste, ShowCharacterPalette, SearchTest);
|
||||
@ -260,7 +260,7 @@ impl TerminalView {
|
||||
has_bell: false,
|
||||
focus_handle: cx.focus_handle(),
|
||||
// todo!()
|
||||
// context_menu: cx.add_view(|cx| ContextMenu::new(view_id, cx)),
|
||||
// context_menu: cx.build_view(|cx| ContextMenu::new(view_id, cx)),
|
||||
blink_state: true,
|
||||
blinking_on: false,
|
||||
blinking_paused: false,
|
||||
@ -493,7 +493,12 @@ pub fn regex_search_for_query(query: &project::search::SearchQuery) -> Option<Re
|
||||
}
|
||||
|
||||
impl TerminalView {
|
||||
fn key_down(&mut self, event: &KeyDownEvent, cx: &mut ViewContext<Self>) -> bool {
|
||||
fn key_down(
|
||||
&mut self,
|
||||
event: &KeyDownEvent,
|
||||
_dispatch_phase: DispatchPhase,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
self.clear_bel(cx);
|
||||
self.pause_cursor_blinking(cx);
|
||||
|
||||
@ -502,7 +507,7 @@ impl TerminalView {
|
||||
&event.keystroke,
|
||||
TerminalSettings::get_global(cx).option_as_meta,
|
||||
)
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn focus_in(&mut self, event: &FocusEvent, cx: &mut ViewContext<Self>) {
|
||||
@ -652,7 +657,10 @@ impl InputHandler for TerminalView {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn selected_text_range(&self, cx: &AppContext) -> Option<std::ops::Range<usize>> {
|
||||
fn selected_text_range(
|
||||
&mut self,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> Option<std::ops::Range<usize>> {
|
||||
if self
|
||||
.terminal
|
||||
.read(cx)
|
||||
@ -706,7 +714,7 @@ impl InputHandler for TerminalView {
|
||||
}
|
||||
|
||||
impl Item for TerminalView {
|
||||
fn tab_tooltip_text(&self, cx: &AppContext) -> Option<Cow<str>> {
|
||||
fn tab_tooltip_text(&self, cx: &AppContext) -> Option<SharedString> {
|
||||
Some(self.terminal().read(cx).title().into())
|
||||
}
|
||||
|
||||
@ -727,7 +735,7 @@ impl Item for TerminalView {
|
||||
&self,
|
||||
_workspace_id: WorkspaceId,
|
||||
_cx: &mut ViewContext<Self>,
|
||||
) -> Option<Self> {
|
||||
) -> Option<View<Self>> {
|
||||
//From what I can tell, there's no way to tell the current working
|
||||
//Directory of the terminal from outside the shell. There might be
|
||||
//solutions to this, but they are non-trivial and require more IPC
|
||||
@ -789,7 +797,7 @@ impl Item for TerminalView {
|
||||
// cx.read(|cx| {
|
||||
// let strategy = TerminalSettings::get_global(cx).working_directory.clone();
|
||||
// workspace
|
||||
// .upgrade(cx)
|
||||
// .upgrade()
|
||||
// .map(|workspace| {
|
||||
// get_working_directory(workspace.read(cx), cx, strategy)
|
||||
// })
|
||||
@ -817,6 +825,10 @@ impl Item for TerminalView {
|
||||
// .detach();
|
||||
self.workspace_id = workspace.database_id();
|
||||
}
|
||||
|
||||
fn focus_handle(&self) -> FocusHandle {
|
||||
self.focus_handle.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl SearchableItem for TerminalView {
|
||||
@ -1098,7 +1110,8 @@ mod tests {
|
||||
let project = Project::test(params.fs.clone(), [], cx).await;
|
||||
let workspace = cx
|
||||
.add_window(|cx| Workspace::test_new(project.clone(), cx))
|
||||
.root_view(cx);
|
||||
.root_view(cx)
|
||||
.unwrap();
|
||||
|
||||
(project, workspace)
|
||||
}
|
||||
|
@ -179,7 +179,7 @@ pub struct Pane {
|
||||
workspace: WeakView<Workspace>,
|
||||
project: Model<Project>,
|
||||
// can_drop: Rc<dyn Fn(&DragAndDrop<Workspace>, &WindowContext) -> bool>,
|
||||
// can_split: bool,
|
||||
can_split: bool,
|
||||
// render_tab_bar_buttons: Rc<dyn Fn(&mut Pane, &mut ViewContext<Pane>) -> AnyElement<Pane>>,
|
||||
}
|
||||
|
||||
@ -347,7 +347,7 @@ impl Pane {
|
||||
workspace,
|
||||
project,
|
||||
// can_drop: Rc::new(|_, _| true),
|
||||
// can_split: true,
|
||||
can_split: true,
|
||||
// render_tab_bar_buttons: Rc::new(move |pane, cx| {
|
||||
// Flex::row()
|
||||
// // New menu
|
||||
@ -427,17 +427,17 @@ impl Pane {
|
||||
// self.can_drop = Rc::new(can_drop);
|
||||
// }
|
||||
|
||||
// pub fn set_can_split(&mut self, can_split: bool, cx: &mut ViewContext<Self>) {
|
||||
// self.can_split = can_split;
|
||||
// cx.notify();
|
||||
// }
|
||||
pub fn set_can_split(&mut self, can_split: bool, cx: &mut ViewContext<Self>) {
|
||||
self.can_split = can_split;
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
// pub fn set_can_navigate(&mut self, can_navigate: bool, cx: &mut ViewContext<Self>) {
|
||||
// self.toolbar.update(cx, |toolbar, cx| {
|
||||
// toolbar.set_can_navigate(can_navigate, cx);
|
||||
// });
|
||||
// cx.notify();
|
||||
// }
|
||||
pub fn set_can_navigate(&mut self, can_navigate: bool, cx: &mut ViewContext<Self>) {
|
||||
self.toolbar.update(cx, |toolbar, cx| {
|
||||
toolbar.set_can_navigate(can_navigate, cx);
|
||||
});
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
// pub fn set_render_tab_bar_buttons<F>(&mut self, cx: &mut ViewContext<Self>, render: F)
|
||||
// where
|
||||
|
@ -36,11 +36,12 @@ use futures::{
|
||||
Future, FutureExt, StreamExt,
|
||||
};
|
||||
use gpui::{
|
||||
actions, div, point, prelude::*, size, Action, AnyModel, AnyView, AnyWeakView, AppContext,
|
||||
actions, div, point, register_action, size, Action, AnyModel, AnyView, AnyWeakView, AppContext,
|
||||
AsyncAppContext, AsyncWindowContext, Bounds, Div, Entity, EntityId, EventEmitter, FocusHandle,
|
||||
FocusableView, GlobalPixels, KeyContext, Model, ModelContext, ParentComponent, Point, Render,
|
||||
Size, Styled, Subscription, Task, View, ViewContext, WeakView, WindowBounds, WindowContext,
|
||||
WindowHandle, WindowOptions,
|
||||
FocusableView, GlobalPixels, KeyContext, Model, ModelContext, ParentElement, Point, Render,
|
||||
Size, StatefulInteractive, StatelessInteractive, StatelessInteractivity, Styled, Subscription,
|
||||
Task, View, ViewContext, VisualContext, WeakView, WindowBounds, WindowContext, WindowHandle,
|
||||
WindowOptions,
|
||||
};
|
||||
use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ItemSettings, ProjectItem};
|
||||
use itertools::Itertools;
|
||||
@ -193,10 +194,11 @@ impl Clone for Toast {
|
||||
}
|
||||
}
|
||||
|
||||
// #[derive(Clone, Deserialize, PartialEq)]
|
||||
// pub struct OpenTerminal {
|
||||
// pub working_directory: PathBuf,
|
||||
// }
|
||||
#[register_action]
|
||||
#[derive(Debug, Default, Clone, Deserialize, PartialEq)]
|
||||
pub struct OpenTerminal {
|
||||
pub working_directory: PathBuf,
|
||||
}
|
||||
|
||||
// impl_actions!(
|
||||
// workspace,
|
||||
@ -206,7 +208,6 @@ impl Clone for Toast {
|
||||
// SwapPaneInDirection,
|
||||
// NewFileInDirection,
|
||||
// Toast,
|
||||
// OpenTerminal,
|
||||
// SaveAll,
|
||||
// Save,
|
||||
// CloseAllItemsAndPanes,
|
||||
|
Loading…
Reference in New Issue
Block a user