Fix bugs resulting from refactoring the terminal into project and workspace halves
This commit is contained in:
parent
83aefffa38
commit
2733f91d8c
7 changed files with 101 additions and 76 deletions
|
@ -199,10 +199,10 @@ macro_rules! query {
|
||||||
use $crate::anyhow::Context;
|
use $crate::anyhow::Context;
|
||||||
|
|
||||||
|
|
||||||
self.write(|connection| {
|
self.write(move |connection| {
|
||||||
let sql_stmt = $crate::sqlez_macros::sql!($($sql)+);
|
let sql_stmt = $crate::sqlez_macros::sql!($($sql)+);
|
||||||
|
|
||||||
connection.select_row_bound::<($($arg_type),+), $return_type>(indoc! { $sql })?(($($arg),+))
|
connection.select_row_bound::<($($arg_type),+), $return_type>(sql_stmt)?(($($arg),+))
|
||||||
.context(::std::format!(
|
.context(::std::format!(
|
||||||
"Error in {}, select_row_bound failed to execute or parse for: {}",
|
"Error in {}, select_row_bound failed to execute or parse for: {}",
|
||||||
::std::stringify!($id),
|
::std::stringify!($id),
|
||||||
|
|
|
@ -199,7 +199,7 @@ impl Default for Shell {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
pub enum AlternateScroll {
|
pub enum AlternateScroll {
|
||||||
On,
|
On,
|
||||||
|
@ -473,6 +473,32 @@ impl Settings {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn terminal_scroll(&self) -> AlternateScroll {
|
||||||
|
*self.terminal_overrides.alternate_scroll.as_ref().unwrap_or(
|
||||||
|
self.terminal_defaults
|
||||||
|
.alternate_scroll
|
||||||
|
.as_ref()
|
||||||
|
.unwrap_or_else(|| &AlternateScroll::On),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn terminal_shell(&self) -> Option<Shell> {
|
||||||
|
self.terminal_overrides
|
||||||
|
.shell
|
||||||
|
.as_ref()
|
||||||
|
.or(self.terminal_defaults.shell.as_ref())
|
||||||
|
.cloned()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn terminal_env(&self) -> HashMap<String, String> {
|
||||||
|
self.terminal_overrides.env.clone().unwrap_or_else(|| {
|
||||||
|
self.terminal_defaults
|
||||||
|
.env
|
||||||
|
.clone()
|
||||||
|
.unwrap_or_else(|| HashMap::default())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(any(test, feature = "test-support"))]
|
#[cfg(any(test, feature = "test-support"))]
|
||||||
pub fn test(cx: &gpui::AppContext) -> Settings {
|
pub fn test(cx: &gpui::AppContext) -> Settings {
|
||||||
Settings {
|
Settings {
|
||||||
|
|
|
@ -269,9 +269,9 @@ impl TerminalBuilder {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
working_directory: Option<PathBuf>,
|
working_directory: Option<PathBuf>,
|
||||||
shell: Option<Shell>,
|
shell: Option<Shell>,
|
||||||
env: Option<HashMap<String, String>>,
|
mut env: HashMap<String, String>,
|
||||||
blink_settings: Option<TerminalBlink>,
|
blink_settings: Option<TerminalBlink>,
|
||||||
alternate_scroll: &AlternateScroll,
|
alternate_scroll: AlternateScroll,
|
||||||
window_id: usize,
|
window_id: usize,
|
||||||
) -> Result<TerminalBuilder> {
|
) -> Result<TerminalBuilder> {
|
||||||
let pty_config = {
|
let pty_config = {
|
||||||
|
@ -288,10 +288,9 @@ impl TerminalBuilder {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut env = env.unwrap_or_default();
|
|
||||||
|
|
||||||
//TODO: Properly set the current locale,
|
//TODO: Properly set the current locale,
|
||||||
env.insert("LC_ALL".to_string(), "en_US.UTF-8".to_string());
|
env.insert("LC_ALL".to_string(), "en_US.UTF-8".to_string());
|
||||||
|
env.insert("ZED_TERM".to_string(), true.to_string());
|
||||||
|
|
||||||
let alac_scrolling = Scrolling::default();
|
let alac_scrolling = Scrolling::default();
|
||||||
// alac_scrolling.set_history((BACK_BUFFER_SIZE * 2) as u32);
|
// alac_scrolling.set_history((BACK_BUFFER_SIZE * 2) as u32);
|
||||||
|
|
|
@ -1,18 +1,16 @@
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use db::{define_connection, query, sqlez_macros::sql};
|
use db::{define_connection, query, sqlez_macros::sql};
|
||||||
use workspace::{WorkspaceDb, WorkspaceId};
|
use workspace::{ItemId, WorkspaceDb, WorkspaceId};
|
||||||
|
|
||||||
type ModelId = usize;
|
|
||||||
|
|
||||||
define_connection! {
|
define_connection! {
|
||||||
pub static ref TERMINAL_DB: TerminalDb<WorkspaceDb> =
|
pub static ref TERMINAL_DB: TerminalDb<WorkspaceDb> =
|
||||||
&[sql!(
|
&[sql!(
|
||||||
CREATE TABLE terminals (
|
CREATE TABLE terminals (
|
||||||
workspace_id INTEGER,
|
workspace_id INTEGER,
|
||||||
model_id INTEGER UNIQUE,
|
item_id INTEGER UNIQUE,
|
||||||
working_directory BLOB,
|
working_directory BLOB,
|
||||||
PRIMARY KEY(workspace_id, model_id),
|
PRIMARY KEY(workspace_id, item_id),
|
||||||
FOREIGN KEY(workspace_id) REFERENCES workspaces(workspace_id)
|
FOREIGN KEY(workspace_id) REFERENCES workspaces(workspace_id)
|
||||||
ON DELETE CASCADE
|
ON DELETE CASCADE
|
||||||
) STRICT;
|
) STRICT;
|
||||||
|
@ -24,7 +22,7 @@ impl TerminalDb {
|
||||||
pub async fn update_workspace_id(
|
pub async fn update_workspace_id(
|
||||||
new_id: WorkspaceId,
|
new_id: WorkspaceId,
|
||||||
old_id: WorkspaceId,
|
old_id: WorkspaceId,
|
||||||
item_id: ModelId
|
item_id: ItemId
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
UPDATE terminals
|
UPDATE terminals
|
||||||
SET workspace_id = ?
|
SET workspace_id = ?
|
||||||
|
@ -34,8 +32,8 @@ impl TerminalDb {
|
||||||
|
|
||||||
query! {
|
query! {
|
||||||
pub async fn save_working_directory(
|
pub async fn save_working_directory(
|
||||||
item_id: ModelId,
|
item_id: ItemId,
|
||||||
workspace_id: i64,
|
workspace_id: WorkspaceId,
|
||||||
working_directory: PathBuf
|
working_directory: PathBuf
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
INSERT OR REPLACE INTO terminals(item_id, workspace_id, working_directory)
|
INSERT OR REPLACE INTO terminals(item_id, workspace_id, working_directory)
|
||||||
|
@ -44,10 +42,10 @@ impl TerminalDb {
|
||||||
}
|
}
|
||||||
|
|
||||||
query! {
|
query! {
|
||||||
pub fn get_working_directory(item_id: ModelId, workspace_id: WorkspaceId) -> Result<Option<PathBuf>> {
|
pub async fn take_working_directory(item_id: ItemId, workspace_id: WorkspaceId) -> Result<Option<PathBuf>> {
|
||||||
SELECT working_directory
|
DELETE FROM terminals
|
||||||
FROM terminals
|
|
||||||
WHERE item_id = ? AND workspace_id = ?
|
WHERE item_id = ? AND workspace_id = ?
|
||||||
|
RETURNING working_directory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ use workspace::{
|
||||||
use workspace::{register_deserializable_item, Pane, WorkspaceId};
|
use workspace::{register_deserializable_item, Pane, WorkspaceId};
|
||||||
|
|
||||||
use project::{LocalWorktree, Project, ProjectPath};
|
use project::{LocalWorktree, Project, ProjectPath};
|
||||||
use settings::{AlternateScroll, Settings, WorkingDirectory};
|
use settings::{Settings, WorkingDirectory};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::ops::RangeInclusive;
|
use std::ops::RangeInclusive;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
@ -99,25 +99,13 @@ impl TerminalContainer {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
working_directory: Option<PathBuf>,
|
working_directory: Option<PathBuf>,
|
||||||
modal: bool,
|
modal: bool,
|
||||||
_workspace_id: WorkspaceId,
|
workspace_id: WorkspaceId,
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let settings = cx.global::<Settings>();
|
let settings = cx.global::<Settings>();
|
||||||
let shell = settings.terminal_overrides.shell.clone();
|
let shell = settings.terminal_shell();
|
||||||
let envs = settings.terminal_overrides.env.clone(); //Should be short and cheap.
|
let envs = settings.terminal_env();
|
||||||
|
let scroll = settings.terminal_scroll();
|
||||||
//TODO: move this pattern to settings
|
|
||||||
let scroll = settings
|
|
||||||
.terminal_overrides
|
|
||||||
.alternate_scroll
|
|
||||||
.as_ref()
|
|
||||||
.unwrap_or(
|
|
||||||
settings
|
|
||||||
.terminal_defaults
|
|
||||||
.alternate_scroll
|
|
||||||
.as_ref()
|
|
||||||
.unwrap_or_else(|| &AlternateScroll::On),
|
|
||||||
);
|
|
||||||
|
|
||||||
let content = match TerminalBuilder::new(
|
let content = match TerminalBuilder::new(
|
||||||
working_directory.clone(),
|
working_directory.clone(),
|
||||||
|
@ -129,7 +117,10 @@ impl TerminalContainer {
|
||||||
) {
|
) {
|
||||||
Ok(terminal) => {
|
Ok(terminal) => {
|
||||||
let terminal = cx.add_model(|cx| terminal.subscribe(cx));
|
let terminal = cx.add_model(|cx| terminal.subscribe(cx));
|
||||||
let view = cx.add_view(|cx| TerminalView::from_terminal(terminal, modal, cx));
|
let item_id = cx.view_id();
|
||||||
|
let view = cx.add_view(|cx| {
|
||||||
|
TerminalView::from_terminal(terminal, modal, workspace_id, item_id, cx)
|
||||||
|
});
|
||||||
|
|
||||||
cx.subscribe(&view, |_this, _content, event, cx| cx.emit(*event))
|
cx.subscribe(&view, |_this, _content, event, cx| cx.emit(*event))
|
||||||
.detach();
|
.detach();
|
||||||
|
@ -394,25 +385,26 @@ impl Item for TerminalContainer {
|
||||||
item_id: workspace::ItemId,
|
item_id: workspace::ItemId,
|
||||||
cx: &mut ViewContext<Pane>,
|
cx: &mut ViewContext<Pane>,
|
||||||
) -> Task<anyhow::Result<ViewHandle<Self>>> {
|
) -> Task<anyhow::Result<ViewHandle<Self>>> {
|
||||||
let working_directory = TERMINAL_DB.get_working_directory(item_id, workspace_id);
|
cx.spawn(|pane, mut cx| async move {
|
||||||
Task::ready(Ok(cx.add_view(|cx| {
|
let cwd = TERMINAL_DB
|
||||||
TerminalContainer::new(
|
.take_working_directory(item_id, workspace_id)
|
||||||
working_directory.log_err().flatten(),
|
.await
|
||||||
false,
|
.log_err()
|
||||||
workspace_id,
|
.flatten();
|
||||||
cx,
|
|
||||||
)
|
cx.update(|cx| {
|
||||||
})))
|
Ok(cx.add_view(pane, |cx| {
|
||||||
|
TerminalContainer::new(cwd, false, workspace_id, cx)
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn added_to_workspace(&mut self, _workspace: &mut Workspace, cx: &mut ViewContext<Self>) {
|
fn added_to_workspace(&mut self, workspace: &mut Workspace, cx: &mut ViewContext<Self>) {
|
||||||
if let Some(_connected) = self.connected() {
|
if let Some(connected) = self.connected() {
|
||||||
// let id = workspace.database_id();
|
connected.update(cx, |connected_view, cx| {
|
||||||
// let terminal_handle = connected.read(cx).terminal().clone();
|
connected_view.added_to_workspace(workspace.database_id(), cx);
|
||||||
//TODO
|
})
|
||||||
cx.background()
|
|
||||||
.spawn(TERMINAL_DB.update_workspace_id(0, 0, 0))
|
|
||||||
.detach();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ use ordered_float::OrderedFloat;
|
||||||
use settings::Settings;
|
use settings::Settings;
|
||||||
use terminal::{
|
use terminal::{
|
||||||
alacritty_terminal::{
|
alacritty_terminal::{
|
||||||
ansi::{Color as AnsiColor, CursorShape as AlacCursorShape, NamedColor},
|
ansi::{Color as AnsiColor, Color::Named, CursorShape as AlacCursorShape, NamedColor},
|
||||||
grid::Dimensions,
|
grid::Dimensions,
|
||||||
index::Point,
|
index::Point,
|
||||||
term::{cell::Flags, TermMode},
|
term::{cell::Flags, TermMode},
|
||||||
|
@ -198,10 +198,7 @@ impl TerminalElement {
|
||||||
|
|
||||||
//Expand background rect range
|
//Expand background rect range
|
||||||
{
|
{
|
||||||
if matches!(
|
if matches!(bg, Named(NamedColor::Background)) {
|
||||||
bg,
|
|
||||||
terminal::alacritty_terminal::ansi::Color::Named(NamedColor::Background)
|
|
||||||
) {
|
|
||||||
//Continue to next cell, resetting variables if nescessary
|
//Continue to next cell, resetting variables if nescessary
|
||||||
cur_alac_color = None;
|
cur_alac_color = None;
|
||||||
if let Some(rect) = cur_rect {
|
if let Some(rect) = cur_rect {
|
||||||
|
@ -639,7 +636,7 @@ impl Element for TerminalElement {
|
||||||
|
|
||||||
//Layout cursor. Rectangle is used for IME, so we should lay it out even
|
//Layout cursor. Rectangle is used for IME, so we should lay it out even
|
||||||
//if we don't end up showing it.
|
//if we don't end up showing it.
|
||||||
let cursor = if let terminal::alacritty_terminal::ansi::CursorShape::Hidden = cursor.shape {
|
let cursor = if let AlacCursorShape::Hidden = cursor.shape {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let cursor_point = DisplayCursor::from(cursor.point, *display_offset);
|
let cursor_point = DisplayCursor::from(cursor.point, *display_offset);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::{ops::RangeInclusive, path::PathBuf, time::Duration};
|
use std::{ops::RangeInclusive, time::Duration};
|
||||||
|
|
||||||
use context_menu::{ContextMenu, ContextMenuItem};
|
use context_menu::{ContextMenu, ContextMenuItem};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
|
@ -21,7 +21,7 @@ use terminal::{
|
||||||
Terminal,
|
Terminal,
|
||||||
};
|
};
|
||||||
use util::ResultExt;
|
use util::ResultExt;
|
||||||
use workspace::pane;
|
use workspace::{pane, ItemId, WorkspaceId};
|
||||||
|
|
||||||
use crate::{persistence::TERMINAL_DB, terminal_element::TerminalElement, Event};
|
use crate::{persistence::TERMINAL_DB, terminal_element::TerminalElement, Event};
|
||||||
|
|
||||||
|
@ -75,6 +75,8 @@ pub struct TerminalView {
|
||||||
blinking_on: bool,
|
blinking_on: bool,
|
||||||
blinking_paused: bool,
|
blinking_paused: bool,
|
||||||
blink_epoch: usize,
|
blink_epoch: usize,
|
||||||
|
workspace_id: WorkspaceId,
|
||||||
|
item_id: ItemId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Entity for TerminalView {
|
impl Entity for TerminalView {
|
||||||
|
@ -85,6 +87,8 @@ impl TerminalView {
|
||||||
pub fn from_terminal(
|
pub fn from_terminal(
|
||||||
terminal: ModelHandle<Terminal>,
|
terminal: ModelHandle<Terminal>,
|
||||||
modal: bool,
|
modal: bool,
|
||||||
|
workspace_id: WorkspaceId,
|
||||||
|
item_id: ItemId,
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
cx.observe(&terminal, |_, _, cx| cx.notify()).detach();
|
cx.observe(&terminal, |_, _, cx| cx.notify()).detach();
|
||||||
|
@ -102,20 +106,20 @@ impl TerminalView {
|
||||||
}
|
}
|
||||||
Event::BlinkChanged => this.blinking_on = !this.blinking_on,
|
Event::BlinkChanged => this.blinking_on = !this.blinking_on,
|
||||||
Event::TitleChanged => {
|
Event::TitleChanged => {
|
||||||
// if let Some(foreground_info) = &terminal.read(cx).foreground_process_info {
|
if let Some(foreground_info) = &this.terminal().read(cx).foreground_process_info {
|
||||||
// let cwd = foreground_info.cwd.clone();
|
let cwd = foreground_info.cwd.clone();
|
||||||
//TODO
|
|
||||||
// let item_id = self.item_id;
|
let item_id = this.item_id;
|
||||||
// let workspace_id = self.workspace_id;
|
let workspace_id = this.workspace_id;
|
||||||
cx.background()
|
cx.background()
|
||||||
.spawn(async move {
|
.spawn(async move {
|
||||||
TERMINAL_DB
|
TERMINAL_DB
|
||||||
.save_working_directory(0, 0, PathBuf::new())
|
.save_working_directory(item_id, workspace_id, cwd)
|
||||||
.await
|
.await
|
||||||
.log_err();
|
.log_err();
|
||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
_ => cx.emit(*event),
|
_ => cx.emit(*event),
|
||||||
})
|
})
|
||||||
|
@ -131,6 +135,8 @@ impl TerminalView {
|
||||||
blinking_on: false,
|
blinking_on: false,
|
||||||
blinking_paused: false,
|
blinking_paused: false,
|
||||||
blink_epoch: 0,
|
blink_epoch: 0,
|
||||||
|
workspace_id,
|
||||||
|
item_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,6 +288,13 @@ impl TerminalView {
|
||||||
&self.terminal
|
&self.terminal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn added_to_workspace(&mut self, new_id: WorkspaceId, cx: &mut ViewContext<Self>) {
|
||||||
|
cx.background()
|
||||||
|
.spawn(TERMINAL_DB.update_workspace_id(new_id, self.workspace_id, self.item_id))
|
||||||
|
.detach();
|
||||||
|
self.workspace_id = new_id;
|
||||||
|
}
|
||||||
|
|
||||||
fn next_blink_epoch(&mut self) -> usize {
|
fn next_blink_epoch(&mut self) -> usize {
|
||||||
self.blink_epoch += 1;
|
self.blink_epoch += 1;
|
||||||
self.blink_epoch
|
self.blink_epoch
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue