vim: Add 'gf' command, make files cmd-clickable (#16534)

Release Notes:

- vim: Added `gf` command to open files under the cursor.
- Filenames can now be `cmd`/`ctrl`-clicked, which opens them.

TODOs:

- [x] `main_test.go` <-- works
- [x] `./my-pkg/my_pkg.go` <-- works
- [x] `../go.mod` <-- works
- [x] `my-pkg/my_pkg.go` <-- works
- [x] `my-pkg/subpkg/subpkg_test.go` <-- works
- [x] `file\ with\ space\ in\ it.txt` <-- works
- [x] `"file\ with\ space\ in\ it.txt"` <-- works
- [x] `"main_test.go"` <-- works
- [x] `/Users/thorstenball/.vimrc` <-- works, but only locally
- [x] `~/.vimrc` <--works, but only locally
- [x] Get it working over collab
- [x] Get hover links working

Demo:



https://github.com/user-attachments/assets/26af7f3b-c392-4aaf-849a-95d6c3b00067

Collab demo:




https://github.com/user-attachments/assets/272598bd-0e82-4556-8f9c-ba53d3a95682
This commit is contained in:
Thorsten Ball 2024-08-22 14:27:11 +02:00 committed by GitHub
parent 1e39d407c2
commit db0c1fd592
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 579 additions and 43 deletions

View file

@ -742,9 +742,15 @@ fn generate_positions(string: &str, query: &str) -> Vec<usize> {
mod test {
use std::path::Path;
use crate::test::{NeovimBackedTestContext, VimTestContext};
use crate::{
state::Mode,
test::{NeovimBackedTestContext, VimTestContext},
};
use editor::Editor;
use gpui::TestAppContext;
use indoc::indoc;
use ui::ViewContext;
use workspace::Workspace;
#[gpui::test]
async fn test_command_basics(cx: &mut TestAppContext) {
@ -923,4 +929,55 @@ mod test {
.await;
cx.shared_state().await.assert_eq("k\nk\nˇk\n4\n4\n3\n2\n1");
}
fn assert_active_item(
workspace: &mut Workspace,
expected_path: &str,
expected_text: &str,
cx: &mut ViewContext<Workspace>,
) {
let active_editor = workspace.active_item_as::<Editor>(cx).unwrap();
let buffer = active_editor
.read(cx)
.buffer()
.read(cx)
.as_singleton()
.unwrap();
let text = buffer.read(cx).text();
let file = buffer.read(cx).file().unwrap();
let file_path = file.as_local().unwrap().abs_path(cx);
assert_eq!(text, expected_text);
assert_eq!(file_path.to_str().unwrap(), expected_path);
}
#[gpui::test]
async fn test_command_gf(cx: &mut TestAppContext) {
let mut cx = VimTestContext::new(cx, true).await;
// Assert base state, that we're in /root/dir/file.rs
cx.workspace(|workspace, cx| {
assert_active_item(workspace, "/root/dir/file.rs", "", cx);
});
// Insert a new file
let fs = cx.workspace(|workspace, cx| workspace.project().read(cx).fs().clone());
fs.as_fake()
.insert_file("/root/dir/file2.rs", "This is file2.rs".as_bytes().to_vec())
.await;
// Put the path to the second file into the currently open buffer
cx.set_state(indoc! {"go to fiˇle2.rs"}, Mode::Normal);
// Go to file2.rs
cx.simulate_keystrokes("g f");
// We now have two items
cx.workspace(|workspace, cx| assert_eq!(workspace.items(cx).count(), 2));
cx.workspace(|workspace, cx| {
assert_active_item(workspace, "/root/dir/file2.rs", "This is file2.rs", cx);
});
}
}