Compare commits
4 commits
main
...
run-comman
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a1a6031c6a | ||
![]() |
2d20b5d850 | ||
![]() |
11ad0b5793 | ||
![]() |
2755cd8ec7 |
5 changed files with 147 additions and 8 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -5070,6 +5070,7 @@ dependencies = [
|
||||||
"multi_buffer",
|
"multi_buffer",
|
||||||
"ordered-float 2.10.1",
|
"ordered-float 2.10.1",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
|
"postage",
|
||||||
"pretty_assertions",
|
"pretty_assertions",
|
||||||
"project",
|
"project",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
|
@ -20462,6 +20463,7 @@ dependencies = [
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"paths",
|
"paths",
|
||||||
"picker",
|
"picker",
|
||||||
|
"postage",
|
||||||
"pretty_assertions",
|
"pretty_assertions",
|
||||||
"profiling",
|
"profiling",
|
||||||
"project",
|
"project",
|
||||||
|
|
|
@ -92,6 +92,7 @@ uuid.workspace = true
|
||||||
workspace.workspace = true
|
workspace.workspace = true
|
||||||
zed_actions.workspace = true
|
zed_actions.workspace = true
|
||||||
workspace-hack.workspace = true
|
workspace-hack.workspace = true
|
||||||
|
postage.workspace = true
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
ctor.workspace = true
|
ctor.workspace = true
|
||||||
|
|
|
@ -176,17 +176,15 @@ use snippet::Snippet;
|
||||||
use std::{
|
use std::{
|
||||||
any::TypeId,
|
any::TypeId,
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
cell::OnceCell,
|
cell::{OnceCell, RefCell},
|
||||||
cell::RefCell,
|
|
||||||
cmp::{self, Ordering, Reverse},
|
cmp::{self, Ordering, Reverse},
|
||||||
iter::Peekable,
|
iter::Peekable,
|
||||||
mem,
|
mem,
|
||||||
num::NonZeroU32,
|
num::NonZeroU32,
|
||||||
ops::Not,
|
ops::{ControlFlow, Deref, DerefMut, Not, Range, RangeInclusive},
|
||||||
ops::{ControlFlow, Deref, DerefMut, Range, RangeInclusive},
|
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
sync::Arc,
|
sync::{Arc, LazyLock},
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
use sum_tree::TreeMap;
|
use sum_tree::TreeMap;
|
||||||
|
@ -237,6 +235,21 @@ pub(crate) const EDIT_PREDICTION_KEY_CONTEXT: &str = "edit_prediction";
|
||||||
pub(crate) const EDIT_PREDICTION_CONFLICT_KEY_CONTEXT: &str = "edit_prediction_conflict";
|
pub(crate) const EDIT_PREDICTION_CONFLICT_KEY_CONTEXT: &str = "edit_prediction_conflict";
|
||||||
pub(crate) const MINIMAP_FONT_SIZE: AbsoluteLength = AbsoluteLength::Pixels(px(2.));
|
pub(crate) const MINIMAP_FONT_SIZE: AbsoluteLength = AbsoluteLength::Pixels(px(2.));
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
|
pub struct LastCursorPosition {
|
||||||
|
pub path: PathBuf,
|
||||||
|
pub worktree_path: Arc<Path>,
|
||||||
|
pub point: Point,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub static LAST_CURSOR_POSITION_WATCH: LazyLock<(
|
||||||
|
Mutex<postage::watch::Sender<Option<LastCursorPosition>>>,
|
||||||
|
postage::watch::Receiver<Option<LastCursorPosition>>,
|
||||||
|
)> = LazyLock::new(|| {
|
||||||
|
let (sender, receiver) = postage::watch::channel();
|
||||||
|
(Mutex::new(sender), receiver)
|
||||||
|
});
|
||||||
|
|
||||||
pub type RenderDiffHunkControlsFn = Arc<
|
pub type RenderDiffHunkControlsFn = Arc<
|
||||||
dyn Fn(
|
dyn Fn(
|
||||||
u32,
|
u32,
|
||||||
|
@ -3018,10 +3031,28 @@ impl Editor {
|
||||||
let new_cursor_position = newest_selection.head();
|
let new_cursor_position = newest_selection.head();
|
||||||
let selection_start = newest_selection.start;
|
let selection_start = newest_selection.start;
|
||||||
|
|
||||||
|
let new_cursor_point = new_cursor_position.to_point(buffer);
|
||||||
|
if let Some(project) = self.project()
|
||||||
|
&& let Some((path, worktree_path)) =
|
||||||
|
self.file_at(new_cursor_point, cx).and_then(|file| {
|
||||||
|
file.as_local().and_then(|file| {
|
||||||
|
let worktree =
|
||||||
|
project.read(cx).worktree_for_id(file.worktree_id(cx), cx)?;
|
||||||
|
Some((file.abs_path(cx), worktree.read(cx).abs_path()))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
{
|
||||||
|
*LAST_CURSOR_POSITION_WATCH.0.lock().borrow_mut() = Some(LastCursorPosition {
|
||||||
|
path,
|
||||||
|
worktree_path,
|
||||||
|
point: new_cursor_point,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if effects.nav_history.is_none() || effects.nav_history == Some(true) {
|
if effects.nav_history.is_none() || effects.nav_history == Some(true) {
|
||||||
self.push_to_nav_history(
|
self.push_to_nav_history(
|
||||||
*old_cursor_position,
|
*old_cursor_position,
|
||||||
Some(new_cursor_position.to_point(buffer)),
|
Some(new_cursor_point),
|
||||||
false,
|
false,
|
||||||
effects.nav_history == Some(true),
|
effects.nav_history == Some(true),
|
||||||
cx,
|
cx,
|
||||||
|
|
|
@ -164,6 +164,7 @@ zed_actions.workspace = true
|
||||||
zeta.workspace = true
|
zeta.workspace = true
|
||||||
zlog.workspace = true
|
zlog.workspace = true
|
||||||
zlog_settings.workspace = true
|
zlog_settings.workspace = true
|
||||||
|
postage.workspace = true
|
||||||
|
|
||||||
[target.'cfg(target_os = "windows")'.dependencies]
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
windows.workspace = true
|
windows.workspace = true
|
||||||
|
|
|
@ -14,9 +14,10 @@ use editor::Editor;
|
||||||
use extension::ExtensionHostProxy;
|
use extension::ExtensionHostProxy;
|
||||||
use extension_host::ExtensionStore;
|
use extension_host::ExtensionStore;
|
||||||
use fs::{Fs, RealFs};
|
use fs::{Fs, RealFs};
|
||||||
use futures::{StreamExt, channel::oneshot, future};
|
use futures::{FutureExt, StreamExt, channel::oneshot, future, select_biased};
|
||||||
use git::GitHostingProviderRegistry;
|
use git::GitHostingProviderRegistry;
|
||||||
use gpui::{App, AppContext as _, Application, AsyncApp, Focusable as _, UpdateGlobal as _};
|
use gpui::{App, AppContext as _, Application, AsyncApp, Focusable as _, UpdateGlobal as _};
|
||||||
|
use postage::stream::Stream as _;
|
||||||
|
|
||||||
use gpui_tokio::Tokio;
|
use gpui_tokio::Tokio;
|
||||||
use http_client::{Url, read_proxy_from_env};
|
use http_client::{Url, read_proxy_from_env};
|
||||||
|
@ -37,7 +38,7 @@ use std::{
|
||||||
env,
|
env,
|
||||||
io::{self, IsTerminal},
|
io::{self, IsTerminal},
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
process,
|
process::{self, Stdio},
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
use theme::{
|
use theme::{
|
||||||
|
@ -732,6 +733,8 @@ pub fn main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// todo! cleanup
|
||||||
|
let fs = app_state.fs.clone();
|
||||||
let app_state = app_state.clone();
|
let app_state = app_state.clone();
|
||||||
|
|
||||||
crate::zed::component_preview::init(app_state.clone(), cx);
|
crate::zed::component_preview::init(app_state.clone(), cx);
|
||||||
|
@ -747,6 +750,107 @@ pub fn main() {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
|
|
||||||
|
if let Ok(selection_change_command) = env::var("ZED_SELECTION_CHANGE_CMD") {
|
||||||
|
log::info!(
|
||||||
|
"Will run {} when the selection changes",
|
||||||
|
selection_change_command
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut cursor_receiver = editor::LAST_CURSOR_POSITION_WATCH.1.clone();
|
||||||
|
cx.background_spawn(async move {
|
||||||
|
// Set up file watcher for the command file
|
||||||
|
let command_path = PathBuf::from(&selection_change_command);
|
||||||
|
let mut file_changes = if command_path.exists() {
|
||||||
|
let (events, _) = fs
|
||||||
|
.watch(&command_path, std::time::Duration::from_millis(100))
|
||||||
|
.await;
|
||||||
|
Some(events)
|
||||||
|
} else {
|
||||||
|
log::warn!(
|
||||||
|
"Command file {} does not exist, only watching selection changes",
|
||||||
|
command_path.display()
|
||||||
|
);
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
loop {
|
||||||
|
select_biased! {
|
||||||
|
// Handle cursor position changes
|
||||||
|
cursor_update = cursor_receiver.recv().fuse() => {
|
||||||
|
if cursor_update.is_none() {
|
||||||
|
// Cursor watcher ended
|
||||||
|
log::warn!("Cursor watcher for {} ended", command_path.display());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Handle file changes to the command file
|
||||||
|
file_change = async {
|
||||||
|
if let Some(ref mut events) = file_changes {
|
||||||
|
events.next().await
|
||||||
|
} else {
|
||||||
|
future::pending().await
|
||||||
|
}
|
||||||
|
}.fuse() => {
|
||||||
|
if file_change.is_none() {
|
||||||
|
// File watcher ended
|
||||||
|
log::warn!("File watcher for {} ended", command_path.display());
|
||||||
|
file_changes = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Could be more efficient
|
||||||
|
let Some(mut cursor) = cursor_receiver.borrow().clone() else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let cursor_position_arg = format!(
|
||||||
|
"{}:{}:{}",
|
||||||
|
cursor.path.display(),
|
||||||
|
cursor.point.row + 1,
|
||||||
|
cursor.point.column + 1
|
||||||
|
);
|
||||||
|
log::info!(
|
||||||
|
"Running {} {} {}",
|
||||||
|
selection_change_command,
|
||||||
|
cursor.worktree_path.display(),
|
||||||
|
cursor_position_arg
|
||||||
|
);
|
||||||
|
let status = smol::process::Command::new(&selection_change_command)
|
||||||
|
.arg(cursor.worktree_path.as_ref())
|
||||||
|
.arg(cursor_position_arg)
|
||||||
|
.stdin(Stdio::null())
|
||||||
|
// todo! It'd be better to distinguish the output in logs.
|
||||||
|
.stdout(Stdio::inherit())
|
||||||
|
.stderr(Stdio::inherit())
|
||||||
|
.status()
|
||||||
|
.await;
|
||||||
|
match status {
|
||||||
|
Ok(status) => {
|
||||||
|
if !status.success() {
|
||||||
|
log::error!("Command failed with status {}", status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
log::error!("Command failed with error {}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let Some(new_cursor) = cursor_receiver.borrow().clone() else {
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
if new_cursor == cursor {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cursor = new_cursor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.detach();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue