Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 110 additions & 2 deletions app/src/tab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::editor::EditorView;
use crate::features::FeatureFlag;
use crate::launch_configs::launch_config::LaunchConfig;
use crate::menu::{MenuAction, MenuItem, MenuItemFields};
use crate::pane_group::PaneGroup;
use crate::pane_group::{PaneGroup, PaneId};
use crate::terminal::model::terminal_model::ConversationTranscriptViewerStatus;
use settings::Setting as _;
use std::sync::Arc;
Expand All @@ -25,7 +25,9 @@ use crate::util::truncation::truncate_from_end;

use crate::window_settings::WindowSettings;
use crate::workspace::sync_inputs::SyncedInputState;
use crate::workspace::tab_settings::{TabCloseButtonPosition, TabSettings};
use crate::workspace::tab_settings::{
TabCloseButtonPosition, TabSettings, VerticalTabsDisplayGranularity,
};
use crate::workspace::{
PaneViewLocator, TabBarDropTargetData, TabBarLocation, TabContextMenuAnchor, WorkspaceAction,
};
Expand Down Expand Up @@ -192,6 +194,7 @@ impl TabData {

for section_items in [
self.session_sharing_menu_items(index, ctx),
self.copy_metadata_menu_items(pane_name_target, ctx),
self.modify_tab_menu_items(index, tabs_len, pane_name_target, ctx),
self.close_tab_menu_items(index, tabs_len, ctx),
Self::save_config_menu_items(index),
Expand Down Expand Up @@ -286,6 +289,111 @@ impl TabData {
menu_items
}

fn copyable_pane_title(
pane_group: &PaneGroup,
pane_id: PaneId,
ctx: &AppContext,
) -> Option<String> {
pane_group.pane_by_id(pane_id).and_then(|pane| {
let configuration = pane.pane_configuration();
let configuration = configuration.as_ref(ctx);
let title = configuration
.custom_vertical_tabs_title()
.unwrap_or_else(|| configuration.title());
Self::copyable_metadata_value(Some(title.to_string()))
})
}

fn copy_metadata_menu_items(
&self,
pane_name_target: Option<PaneNameMenuTarget>,
ctx: &AppContext,
) -> Vec<MenuItem<WorkspaceAction>> {
let pane_group = self.pane_group.as_ref(ctx);
let mut menu_items = vec![];
let tab_title = Self::copyable_metadata_value(Some(pane_group.display_title(ctx)));
if !uses_vertical_tabs(ctx) {
Self::push_copy_metadata_menu_item(&mut menu_items, "Copy tab title", tab_title);
return menu_items;
}

let vertical_tabs_display_granularity = *TabSettings::as_ref(ctx)
.vertical_tabs_display_granularity
.value();
let (title_label, title, terminal_view) = if matches!(
vertical_tabs_display_granularity,
VerticalTabsDisplayGranularity::Panes
) {
let pane_id = pane_name_target
.filter(|target| self.pane_group.id() == target.locator.pane_group_id)
.and_then(|target| {
pane_group
.pane_by_id(target.locator.pane_id)
.map(|_| target.locator.pane_id)
})
.unwrap_or_else(|| pane_group.focused_pane_id(ctx));
(
"Copy pane title",
Self::copyable_pane_title(pane_group, pane_id, ctx),
pane_group.terminal_view_from_pane_id(pane_id, ctx),
)
} else {
let terminal_view = pane_name_target
.filter(|target| self.pane_group.id() == target.locator.pane_group_id)
.and_then(|target| {
pane_group.terminal_view_from_pane_id(target.locator.pane_id, ctx)
})
.or_else(|| pane_group.focused_session_view(ctx));
("Copy tab title", tab_title, terminal_view)
};

if let Some(terminal_view) = terminal_view {
let terminal_view = terminal_view.as_ref(ctx);
Self::push_copy_metadata_menu_item(
&mut menu_items,
"Copy branch",
Self::copyable_metadata_value(terminal_view.current_git_branch(ctx)),
);
Self::push_copy_metadata_menu_item(&mut menu_items, title_label, title);
Self::push_copy_metadata_menu_item(
&mut menu_items,
"Copy working directory",
Self::copyable_metadata_value(
terminal_view
.pwd()
.or_else(|| terminal_view.display_working_directory(ctx)),
),
);
Self::push_copy_metadata_menu_item(
&mut menu_items,
"Copy pull request link",
Self::copyable_metadata_value(terminal_view.current_pull_request_url(ctx)),
);
} else {
Self::push_copy_metadata_menu_item(&mut menu_items, title_label, title);
}

menu_items
}

fn push_copy_metadata_menu_item(
menu_items: &mut Vec<MenuItem<WorkspaceAction>>,
label: &'static str,
value: Option<String>,
) {
if let Some(value) = value {
menu_items.push(
MenuItemFields::new(label)
.with_on_select_action(WorkspaceAction::CopyTextToClipboard(value))
.into_item(),
);
}
}

fn copyable_metadata_value(value: Option<String>) -> Option<String> {
value.filter(|value| !value.trim().is_empty())
}

fn modify_tab_menu_items(
&self,
index: usize,
Expand Down
3 changes: 3 additions & 0 deletions crates/integration/src/bin/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,9 @@ fn register_tests() -> HashMap<&'static str, BoxedBuilderFn> {
register_test!(test_context_chips_prompt_at_bootstrap);

register_test!(test_active_session_follows_focus);
register_test!(test_tab_context_menu_copies_metadata);
register_test!(test_vertical_tab_context_menu_copies_metadata);
register_test!(test_vertical_pane_context_menu_copies_metadata);

register_test!(test_focus_panes_on_hover);

Expand Down
Loading
Loading