mod.rs

  1pub mod pane;
  2pub mod pane_group;
  3pub mod workspace;
  4pub mod workspace_view;
  5
  6pub use pane::*;
  7pub use pane_group::*;
  8pub use workspace::*;
  9pub use workspace_view::*;
 10
 11use crate::{settings::Settings, watch};
 12use gpui::{App, MutableAppContext};
 13use std::path::PathBuf;
 14
 15pub fn init(app: &mut App) {
 16    app.add_global_action("workspace:open_paths", open_paths);
 17    pane::init(app);
 18}
 19
 20pub struct OpenParams {
 21    pub paths: Vec<PathBuf>,
 22    pub settings: watch::Receiver<Settings>,
 23}
 24
 25fn open_paths(params: &OpenParams, app: &mut MutableAppContext) {
 26    log::info!("open paths {:?}", params.paths);
 27
 28    // Open paths in existing workspace if possible
 29    for window_id in app.window_ids().collect::<Vec<_>>() {
 30        if let Some(handle) = app.root_view::<WorkspaceView>(window_id) {
 31            if handle.update(app, |view, ctx| {
 32                if view.contains_paths(&params.paths, ctx.app()) {
 33                    view.open_paths(&params.paths, ctx.app_mut());
 34                    log::info!("open paths on existing workspace");
 35                    true
 36                } else {
 37                    false
 38                }
 39            }) {
 40                return;
 41            }
 42        }
 43    }
 44
 45    log::info!("open new workspace");
 46
 47    // Add a new workspace if necessary
 48    let workspace = app.add_model(|ctx| Workspace::new(params.paths.clone(), ctx));
 49    app.add_window(|ctx| WorkspaceView::new(workspace, params.settings.clone(), ctx));
 50}
 51
 52#[cfg(test)]
 53mod tests {
 54    use super::*;
 55    use crate::{settings, test::*};
 56    use gpui::{App, FontCache};
 57    use serde_json::json;
 58
 59    #[test]
 60    fn test_open_paths_action() {
 61        App::test(|mut app| async move {
 62            let settings = settings::channel(&FontCache::new()).unwrap().1;
 63
 64            init(&mut app);
 65
 66            let dir = temp_tree(json!({
 67                "a": {
 68                    "aa": null,
 69                    "ab": null,
 70                },
 71                "b": {
 72                    "ba": null,
 73                    "bb": null,
 74                },
 75                "c": {
 76                    "ca": null,
 77                    "cb": null,
 78                },
 79            }));
 80
 81            app.dispatch_global_action(
 82                "workspace:open_paths",
 83                OpenParams {
 84                    paths: vec![
 85                        dir.path().join("a").to_path_buf(),
 86                        dir.path().join("b").to_path_buf(),
 87                    ],
 88                    settings: settings.clone(),
 89                },
 90            );
 91            assert_eq!(app.window_ids().len(), 1);
 92
 93            app.dispatch_global_action(
 94                "workspace:open_paths",
 95                OpenParams {
 96                    paths: vec![dir.path().join("a").to_path_buf()],
 97                    settings: settings.clone(),
 98                },
 99            );
100            assert_eq!(app.window_ids().len(), 1);
101            let workspace_view_1 = app.root_view::<WorkspaceView>(app.window_ids()[0]).unwrap();
102            workspace_view_1.read(&app, |view, app| {
103                assert_eq!(view.workspace.as_ref(app).worktrees().len(), 2);
104            });
105
106            app.dispatch_global_action(
107                "workspace:open_paths",
108                OpenParams {
109                    paths: vec![
110                        dir.path().join("b").to_path_buf(),
111                        dir.path().join("c").to_path_buf(),
112                    ],
113                    settings: settings.clone(),
114                },
115            );
116            assert_eq!(app.window_ids().len(), 2);
117        });
118    }
119}