@@ -33,6 +33,7 @@ use mappings::mouse::{
use procinfo::LocalProcessInfo;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
+use smol::channel::Sender;
use util::truncate_and_trailoff;
use std::{
@@ -89,10 +90,12 @@ pub enum Event {
Wakeup,
BlinkChanged,
SelectionsChanged,
- Open {
- is_url: bool,
- maybe_url_or_path: String,
+ OpenUrl(String),
+ ProbePathOpen {
+ maybe_path: String,
+ can_open_tx: Sender<bool>,
},
+ OpenPath(String),
}
#[derive(Clone)]
@@ -874,12 +877,43 @@ impl Terminal {
if let Some((maybe_url_or_path, is_url, url_match)) = found_url {
if *open {
- cx.emit(Event::Open {
- is_url,
- maybe_url_or_path,
- })
+ let event = if is_url {
+ Event::OpenUrl(maybe_url_or_path)
+ } else {
+ Event::OpenPath(maybe_url_or_path)
+ };
+ cx.emit(event);
} else {
- self.update_selected_word(prev_hovered_word, maybe_url_or_path, url_match);
+ if is_url {
+ self.update_selected_word(
+ prev_hovered_word,
+ maybe_url_or_path,
+ url_match,
+ );
+ } else {
+ let (can_open_tx, can_open_rx) = smol::channel::bounded(1);
+ cx.emit(Event::ProbePathOpen {
+ maybe_path: maybe_url_or_path.clone(),
+ can_open_tx,
+ });
+
+ cx.spawn(|terminal, mut cx| async move {
+ let can_open = can_open_rx.recv().await.unwrap_or(false);
+ terminal.update(&mut cx, |terminal, cx| {
+ if can_open {
+ terminal.update_selected_word(
+ prev_hovered_word,
+ maybe_url_or_path,
+ url_match,
+ );
+ } else {
+ terminal.last_content.last_hovered_word.take();
+ }
+ cx.notify();
+ });
+ })
+ .detach();
+ };
}
}
}
@@ -166,42 +166,27 @@ impl TerminalView {
.detach();
}
}
- Event::Open {
- is_url,
- maybe_url_or_path,
+ Event::ProbePathOpen {
+ maybe_path,
+ can_open_tx,
} => {
- if *is_url {
- cx.platform().open_url(maybe_url_or_path);
- } else if let Some(workspace) = workspace.upgrade(cx) {
- let path_like =
- PathLikeWithPosition::parse_str(maybe_url_or_path.as_str(), |path_str| {
- Ok::<_, std::convert::Infallible>(Path::new(path_str).to_path_buf())
- })
- .expect("infallible");
- let maybe_path = path_like.path_like;
- workspace.update(cx, |workspace, cx| {
- let potential_abs_paths = if maybe_path.is_absolute() {
- vec![maybe_path]
- } else {
+ let can_open = !possible_open_targets(&workspace, maybe_path, cx).is_empty();
+ can_open_tx.send_blocking(can_open).ok();
+ }
+ Event::OpenUrl(url) => cx.platform().open_url(url),
+ Event::OpenPath(maybe_path) => {
+ let potential_abs_paths = possible_open_targets(&workspace, maybe_path, cx);
+ if let Some(path) = potential_abs_paths.into_iter().next() {
+ // TODO kb change selections using path_like row & column
+ let visible = path.path_like.is_dir();
+ if let Some(workspace) = workspace.upgrade(cx) {
+ workspace.update(cx, |workspace, cx| {
workspace
- .worktrees(cx)
- .map(|worktree| worktree.read(cx).abs_path().join(&maybe_path))
- .collect()
- };
-
- for path in potential_abs_paths {
- if path.exists() {
- let visible = path.is_dir();
- workspace
- .open_abs_path(path, visible, cx)
- .detach_and_log_err(cx);
- break;
- }
- }
- });
+ .open_abs_path(path.path_like, visible, cx)
+ .detach_and_log_err(cx);
+ });
+ }
}
-
- // TODO kb let terminal know if we cannot open the string + remove the error message when folder open returns None
}
_ => cx.emit(event.clone()),
})
@@ -389,6 +374,40 @@ impl TerminalView {
}
}
+fn possible_open_targets(
+ workspace: &WeakViewHandle<Workspace>,
+ maybe_path: &String,
+ cx: &mut ViewContext<'_, '_, TerminalView>,
+) -> Vec<PathLikeWithPosition<PathBuf>> {
+ let path_like = PathLikeWithPosition::parse_str(maybe_path.as_str(), |path_str| {
+ Ok::<_, std::convert::Infallible>(Path::new(path_str).to_path_buf())
+ })
+ .expect("infallible");
+ let maybe_path = path_like.path_like;
+ let potential_abs_paths = if maybe_path.is_absolute() {
+ vec![maybe_path]
+ } else if let Some(workspace) = workspace.upgrade(cx) {
+ workspace.update(cx, |workspace, cx| {
+ workspace
+ .worktrees(cx)
+ .map(|worktree| worktree.read(cx).abs_path().join(&maybe_path))
+ .collect()
+ })
+ } else {
+ Vec::new()
+ };
+
+ potential_abs_paths
+ .into_iter()
+ .filter(|path| path.exists())
+ .map(|path| PathLikeWithPosition {
+ path_like: path,
+ row: path_like.row,
+ column: path_like.column,
+ })
+ .collect()
+}
+
pub fn regex_search_for_query(query: project::search::SearchQuery) -> Option<RegexSearch> {
let searcher = match query {
project::search::SearchQuery::Text { query, .. } => RegexSearch::new(&query),