1// Projections allow users to associate files within a project as projections of
2// one another. Inspired by https://github.com/tpope/vim-projectionist .
3//
4// Take, for example, a newly generated Phoenix project. Among other files, one
5// can find the page controller module and its corresponding test file in:
6//
7// - `lib/app_web/controllers/page_controller.ex`
8// - `lib/app_web/controllers/page_controller_test.exs`
9//
10// From the point of view of the controller module, one can say that the test
11// file is a projection of the controller module, and vice versa.
12//
13// TODO!:
14// - [ ] Implement `:a` to open alternate file
15// - [ ] Implement `:as` to open alternate file in split
16// - [ ] Implement `:av` to open alternate file in vertical split
17// - [ ] Implement actually updating the state from the `projections.json` file
18// - [ ] Make this work with excerpts in multibuffers
19
20use crate::Vim;
21use editor::Editor;
22use gpui::Context;
23use gpui::Window;
24use gpui::actions;
25use project::ProjectItem;
26use project::ProjectPath;
27use util::rel_path::RelPath;
28
29actions!(
30 vim,
31 [
32 /// Opens a projection of the current file.
33 OpenProjection,
34 ]
35);
36
37pub fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
38 Vim::action(editor, cx, Vim::open_projection);
39}
40
41impl Vim {
42 pub fn open_projection(
43 &mut self,
44 _: &OpenProjection,
45 window: &mut Window,
46 cx: &mut Context<Self>,
47 ) {
48 // Implementation for opening a projection
49 dbg!("[vim] attempting to open projection...");
50 self.update_editor(cx, |_vim, editor, cx| {
51 let project_path = editor
52 .buffer()
53 .read(cx)
54 .as_singleton()
55 .and_then(|buffer| buffer.read(cx).project_path(cx));
56
57 // User is editing an empty buffer, can't even find a projection.
58 if project_path.is_none() {
59 return;
60 }
61
62 if let Some(project_path) = project_path
63 && let Some(workspace) = editor.workspace()
64 {
65 dbg!(&project_path);
66 if project_path.path.as_unix_str()
67 == "lib/phx_new_web/controllers/page_controller.ex"
68 {
69 dbg!("[vim] opening projection...");
70 workspace
71 .update(cx, |workspace, cx| {
72 let worktree_id = project_path.worktree_id;
73 let mut project_path = ProjectPath::root_path(worktree_id);
74 project_path.path = RelPath::unix(
75 "test/phx_new_web/controllers/page_controller_test.exs",
76 )
77 .unwrap()
78 .into_arc();
79 dbg!(&project_path);
80
81 workspace.open_path(project_path, None, true, window, cx)
82 })
83 .detach();
84 }
85 }
86 });
87 }
88}