Skip to content

Commit ecd35f5

Browse files
committed
Show error message if copy to clipboard fails
- Draw `msg` after `inspect_commit_popup` to make sure the error message is visible - Move `try_or_popup!` to `utils`
1 parent 42c0d9d commit ecd35f5

File tree

6 files changed

+62
-56
lines changed

6 files changed

+62
-56
lines changed

src/app.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -515,8 +515,8 @@ impl App {
515515
self.stashmsg_popup.draw(f, size)?;
516516
self.reset.draw(f, size)?;
517517
self.help.draw(f, size)?;
518-
self.msg.draw(f, size)?;
519518
self.inspect_commit_popup.draw(f, size)?;
519+
self.msg.draw(f, size)?;
520520
self.external_editor_popup.draw(f, size)?;
521521
self.tag_commit_popup.draw(f, size)?;
522522

src/components/changes.rs

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::{
77
components::{CommandInfo, Component},
88
keys,
99
queue::{Action, InternalEvent, NeedsUpdate, Queue, ResetItem},
10-
strings,
10+
strings, try_or_popup,
1111
ui::style::SharedTheme,
1212
};
1313
use anyhow::Result;
@@ -17,22 +17,6 @@ use std::path::Path;
1717
use strings::commands;
1818
use tui::{backend::Backend, layout::Rect, Frame};
1919

20-
/// macro to simplify running code that might return Err.
21-
/// It will show a popup in that case
22-
#[macro_export]
23-
macro_rules! try_or_popup {
24-
($self:ident, $msg:literal, $e:expr) => {
25-
if let Err(err) = $e {
26-
$self.queue.borrow_mut().push_back(
27-
InternalEvent::ShowErrorMsg(format!(
28-
"{}\n{}",
29-
$msg, err
30-
)),
31-
);
32-
}
33-
};
34-
}
35-
3620
///
3721
pub struct ChangesComponent {
3822
title: String,

src/components/diff.rs

Lines changed: 42 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::{
66
keys,
77
queue::{Action, InternalEvent, NeedsUpdate, Queue, ResetItem},
88
strings::{self, commands},
9+
try_or_popup,
910
ui::{calc_scroll_top, style::SharedTheme},
1011
};
1112
use asyncgit::{hash, sync, DiffLine, DiffLineType, FileDiff, CWD};
@@ -21,7 +22,7 @@ use tui::{
2122
Frame,
2223
};
2324

24-
use anyhow::Result;
25+
use anyhow::{anyhow, Result};
2526

2627
#[derive(Default)]
2728
struct Current {
@@ -103,13 +104,18 @@ pub struct DiffComponent {
103104
focused: bool,
104105
current: Current,
105106
scroll_top: Cell<usize>,
106-
queue: Option<Queue>,
107+
queue: Queue,
107108
theme: SharedTheme,
109+
is_immutable: bool,
108110
}
109111

110112
impl DiffComponent {
111113
///
112-
pub fn new(queue: Option<Queue>, theme: SharedTheme) -> Self {
114+
pub fn new(
115+
queue: Queue,
116+
theme: SharedTheme,
117+
is_immutable: bool,
118+
) -> Self {
113119
Self {
114120
focused: false,
115121
queue,
@@ -121,6 +127,7 @@ impl DiffComponent {
121127
selection: Selection::Single(0),
122128
scroll_top: Cell::new(0),
123129
theme,
130+
is_immutable,
124131
}
125132
}
126133
///
@@ -228,6 +235,18 @@ impl DiffComponent {
228235
Ok(())
229236
}
230237

238+
fn copy_string(string: String) -> Result<()> {
239+
let mut ctx: ClipboardContext = ClipboardProvider::new()
240+
.map_err(|_| {
241+
anyhow!("failed to get access to clipboard")
242+
})?;
243+
ctx.set_contents(string).map_err(|_| {
244+
anyhow!("failed to set clipboard contents")
245+
})?;
246+
247+
Ok(())
248+
}
249+
231250
fn copy_selection(&self) -> Result<()> {
232251
if let Some(diff) = &self.diff {
233252
let lines_to_copy: Vec<&str> = diff
@@ -250,10 +269,11 @@ impl DiffComponent {
250269
})
251270
.collect();
252271

253-
let mut ctx: ClipboardContext = ClipboardProvider::new()
254-
.expect("failed to get access to clipboard");
255-
ctx.set_contents(lines_to_copy.join("\n"))
256-
.expect("failed to set clipboard contents");
272+
try_or_popup!(
273+
self,
274+
"copy to clipboard error:",
275+
Self::copy_string(lines_to_copy.join("\n"))
276+
);
257277
}
258278

259279
Ok(())
@@ -483,7 +503,6 @@ impl DiffComponent {
483503
fn queue_update(&mut self) {
484504
self.queue
485505
.as_ref()
486-
.expect("try using queue in immutable diff")
487506
.borrow_mut()
488507
.push_back(InternalEvent::Update(NeedsUpdate::ALL));
489508
}
@@ -493,40 +512,28 @@ impl DiffComponent {
493512
if let Some(hunk) = self.selected_hunk {
494513
let hash = diff.hunks[hunk].header_hash;
495514

496-
self.queue
497-
.as_ref()
498-
.expect("try using queue in immutable diff")
499-
.borrow_mut()
500-
.push_back(InternalEvent::ConfirmAction(
501-
Action::ResetHunk(
502-
self.current.path.clone(),
503-
hash,
504-
),
505-
));
515+
self.queue.as_ref().borrow_mut().push_back(
516+
InternalEvent::ConfirmAction(Action::ResetHunk(
517+
self.current.path.clone(),
518+
hash,
519+
)),
520+
);
506521
}
507522
}
508523
Ok(())
509524
}
510525

511526
fn reset_untracked(&self) -> Result<()> {
512-
self.queue
513-
.as_ref()
514-
.expect("try using queue in immutable diff")
515-
.borrow_mut()
516-
.push_back(InternalEvent::ConfirmAction(Action::Reset(
517-
ResetItem {
518-
path: self.current.path.clone(),
519-
is_folder: false,
520-
},
521-
)));
527+
self.queue.as_ref().borrow_mut().push_back(
528+
InternalEvent::ConfirmAction(Action::Reset(ResetItem {
529+
path: self.current.path.clone(),
530+
is_folder: false,
531+
})),
532+
);
522533

523534
Ok(())
524535
}
525536

526-
fn is_immutable(&self) -> bool {
527-
self.queue.is_none()
528-
}
529-
530537
const fn is_stage(&self) -> bool {
531538
self.current.is_stage
532539
}
@@ -603,7 +610,7 @@ impl Component for DiffComponent {
603610
.hidden(),
604611
);
605612

606-
if !self.is_immutable() {
613+
if !self.is_immutable {
607614
out.push(CommandInfo::new(
608615
commands::DIFF_HUNK_REMOVE,
609616
self.selected_hunk.is_some(),
@@ -660,7 +667,7 @@ impl Component for DiffComponent {
660667
self.move_selection(ScrollType::PageDown)?;
661668
Ok(true)
662669
}
663-
keys::ENTER if !self.is_immutable() => {
670+
keys::ENTER if !self.is_immutable => {
664671
if self.current.is_stage {
665672
self.unstage_hunk()?;
666673
} else {
@@ -669,8 +676,7 @@ impl Component for DiffComponent {
669676
Ok(true)
670677
}
671678
keys::DIFF_RESET_HUNK
672-
if !self.is_immutable()
673-
&& !self.is_stage() =>
679+
if !self.is_immutable && !self.is_stage() =>
674680
{
675681
if let Some(diff) = &self.diff {
676682
if diff.untracked {

src/components/inspect_commit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ impl InspectCommitComponent {
159159
sender,
160160
theme.clone(),
161161
),
162-
diff: DiffComponent::new(None, theme),
162+
diff: DiffComponent::new(queue.clone(), theme, true),
163163
commit_id: None,
164164
tags: None,
165165
git_diff: AsyncDiff::new(sender.clone()),

src/components/utils/mod.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,22 @@ pub mod filetree;
44
pub mod logitems;
55
pub mod statustree;
66

7+
/// macro to simplify running code that might return Err.
8+
/// It will show a popup in that case
9+
#[macro_export]
10+
macro_rules! try_or_popup {
11+
($self:ident, $msg:literal, $e:expr) => {
12+
if let Err(err) = $e {
13+
$self.queue.borrow_mut().push_back(
14+
InternalEvent::ShowErrorMsg(format!(
15+
"{}\n{}",
16+
$msg, err
17+
)),
18+
);
19+
}
20+
};
21+
}
22+
723
/// helper func to convert unix time since epoch to formated time string in local timezone
824
pub fn time_to_string(secs: i64, short: bool) -> String {
925
let time = DateTime::<Local>::from(DateTime::<Utc>::from_utc(

src/tabs/status.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ impl Status {
127127
queue.clone(),
128128
theme.clone(),
129129
),
130-
diff: DiffComponent::new(Some(queue.clone()), theme),
130+
diff: DiffComponent::new(queue.clone(), theme, false),
131131
git_diff: AsyncDiff::new(sender.clone()),
132132
git_status_workdir: AsyncStatus::new(sender.clone()),
133133
git_status_stage: AsyncStatus::new(sender.clone()),

0 commit comments

Comments
 (0)