Skip to content

Commit 0454e2a

Browse files
author
Stephan Dilly
committed
asyncjob supports sending arbitrary notifications
this is used to send progress reports during work on the job
1 parent b9e4631 commit 0454e2a

File tree

8 files changed

+178
-52
lines changed

8 files changed

+178
-52
lines changed

asyncgit/src/asyncjob/mod.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ pub trait AsyncJob: Send + Sync + Clone {
1212
type Notification: Copy + Send + 'static;
1313

1414
/// can run a synchronous time intensive task
15-
fn run(&mut self) -> Self::Notification;
15+
fn run(
16+
&mut self,
17+
sender: Sender<Self::Notification>,
18+
) -> Result<Self::Notification>;
1619
}
1720

1821
/// Abstraction for a FIFO task queue that will only queue up **one** `next` job.
@@ -95,7 +98,7 @@ impl<J: 'static + AsyncJob> AsyncSingleJob<J> {
9598
{
9699
let _pending = self.pending.lock()?;
97100

98-
let notification = task.run();
101+
let notification = task.run(self.sender.clone())?;
99102

100103
if let Ok(mut last) = self.last.lock() {
101104
*last = Some(task);
@@ -147,7 +150,10 @@ mod test {
147150
impl AsyncJob for TestJob {
148151
type Notification = TestNotificaton;
149152

150-
fn run(&mut self) -> Self::Notification {
153+
fn run(
154+
&mut self,
155+
_sender: Sender<Self::Notification>,
156+
) -> Result<Self::Notification> {
151157
println!("[job] wait");
152158

153159
while !self.finish.load(Ordering::SeqCst) {
@@ -165,7 +171,7 @@ mod test {
165171

166172
println!("[job] value: {}", res);
167173

168-
()
174+
Ok(())
169175
}
170176
}
171177

asyncgit/src/error.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,51 +3,67 @@
33
use std::{num::TryFromIntError, string::FromUtf8Error};
44
use thiserror::Error;
55

6+
///
67
#[derive(Error, Debug)]
78
pub enum Error {
9+
///
810
#[error("`{0}`")]
911
Generic(String),
1012

13+
///
1114
#[error("git: no head found")]
1215
NoHead,
1316

17+
///
1418
#[error("git: conflict during rebase")]
1519
RebaseConflict,
1620

21+
///
1722
#[error("git: remote url not found")]
1823
UnknownRemote,
1924

25+
///
2026
#[error("git: inconclusive remotes")]
2127
NoDefaultRemoteFound,
2228

29+
///
2330
#[error("git: work dir error")]
2431
NoWorkDir,
2532

33+
///
2634
#[error("git: uncommitted changes")]
2735
UncommittedChanges,
2836

37+
///
2938
#[error("git: can\u{2019}t run blame on a binary file")]
3039
NoBlameOnBinaryFile,
3140

41+
///
3242
#[error("binary file")]
3343
BinaryFile,
3444

45+
///
3546
#[error("io error:{0}")]
3647
Io(#[from] std::io::Error),
3748

49+
///
3850
#[error("git error:{0}")]
3951
Git(#[from] git2::Error),
4052

53+
///
4154
#[error("utf8 error:{0}")]
4255
Utf8Conversion(#[from] FromUtf8Error),
4356

57+
///
4458
#[error("TryFromInt error:{0}")]
4559
IntConversion(#[from] TryFromIntError),
4660

61+
///
4762
#[error("EasyCast error:{0}")]
4863
EasyCast(#[from] easy_cast::Error),
4964
}
5065

66+
///
5167
pub type Result<T> = std::result::Result<T, Error>;
5268

5369
impl<T> From<std::sync::PoisonError<T>> for Error {

asyncgit/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ pub use crate::{
4343
blame::{AsyncBlame, BlameParams},
4444
commit_files::{AsyncCommitFiles, CommitFilesParams},
4545
diff::{AsyncDiff, DiffParams, DiffType},
46+
error::{Error, Result},
4647
fetch::{AsyncFetch, FetchRequest},
48+
progress::ProgressPercent,
4749
push::{AsyncPush, PushRequest},
4850
push_tags::{AsyncPushTags, PushTagsRequest},
4951
remote_progress::{RemoteProgress, RemoteProgressState},

asyncgit/src/progress.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use easy_cast::{Conv, ConvFloat};
44
use std::cmp;
55

66
///
7-
#[derive(Clone, Debug)]
7+
#[derive(Clone, Copy, Debug, PartialEq)]
88
pub struct ProgressPercent {
99
/// percent 0..100
1010
pub progress: u8,

asyncgit/src/remote_tags.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//!
22
3+
use crossbeam_channel::Sender;
4+
35
use crate::{
46
asyncjob::AsyncJob,
57
error::Result,
@@ -52,7 +54,10 @@ impl AsyncRemoteTagsJob {
5254
impl AsyncJob for AsyncRemoteTagsJob {
5355
type Notification = AsyncGitNotification;
5456

55-
fn run(&mut self) -> Self::Notification {
57+
fn run(
58+
&mut self,
59+
_sender: Sender<Self::Notification>,
60+
) -> Result<Self::Notification> {
5661
if let Ok(mut state) = self.state.lock() {
5762
*state = state.take().map(|state| match state {
5863
JobState::Request(basic_credential) => {
@@ -73,6 +78,6 @@ impl AsyncJob for AsyncRemoteTagsJob {
7378
});
7479
}
7580

76-
AsyncGitNotification::RemoteTags
81+
Ok(AsyncGitNotification::RemoteTags)
7782
}
7883
}

src/components/syntax_text.rs

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ use crate::{
99
self, common_nav, style::SharedTheme, AsyncSyntaxJob,
1010
ParagraphState, ScrollPos, StatefulParagraph,
1111
},
12-
AsyncAppNotification, AsyncNotification,
12+
AsyncAppNotification, AsyncNotification, SyntaxHighlightProgress,
1313
};
1414
use anyhow::Result;
1515
use asyncgit::{
1616
asyncjob::AsyncSingleJob,
1717
sync::{self, TreeFile},
18-
CWD,
18+
ProgressPercent, CWD,
1919
};
2020
use crossbeam_channel::Sender;
2121
use crossterm::event::Event;
@@ -33,6 +33,7 @@ use tui::{
3333
pub struct SyntaxTextComponent {
3434
current_file: Option<(String, Either<ui::SyntaxText, String>)>,
3535
async_highlighting: AsyncSingleJob<AsyncSyntaxJob>,
36+
syntax_progress: Option<ProgressPercent>,
3637
key_config: SharedKeyConfig,
3738
paragraph_state: Cell<ParagraphState>,
3839
focused: bool,
@@ -48,6 +49,7 @@ impl SyntaxTextComponent {
4849
) -> Self {
4950
Self {
5051
async_highlighting: AsyncSingleJob::new(sender.clone()),
52+
syntax_progress: None,
5153
current_file: None,
5254
paragraph_state: Cell::new(ParagraphState::default()),
5355
focused: false,
@@ -58,19 +60,27 @@ impl SyntaxTextComponent {
5860

5961
///
6062
pub fn update(&mut self, ev: AsyncNotification) {
61-
if matches!(
62-
ev,
63-
AsyncNotification::App(
64-
AsyncAppNotification::SyntaxHighlighting
65-
)
66-
) {
67-
if let Some(job) = self.async_highlighting.take_last() {
68-
if let Some((path, content)) =
69-
self.current_file.as_mut()
70-
{
71-
if let Some(syntax) = job.result() {
72-
if syntax.path() == Path::new(path) {
73-
*content = Either::Left(syntax);
63+
if let AsyncNotification::App(
64+
AsyncAppNotification::SyntaxHighlighting(progress),
65+
) = ev
66+
{
67+
match progress {
68+
SyntaxHighlightProgress::Progress(progress) => {
69+
self.syntax_progress = Some(progress);
70+
}
71+
SyntaxHighlightProgress::Done => {
72+
self.syntax_progress = None;
73+
if let Some(job) =
74+
self.async_highlighting.take_last()
75+
{
76+
if let Some((path, content)) =
77+
self.current_file.as_mut()
78+
{
79+
if let Some(syntax) = job.result() {
80+
if syntax.path() == Path::new(path) {
81+
*content = Either::Left(syntax);
82+
}
83+
}
7484
}
7585
}
7686
}
@@ -101,6 +111,8 @@ impl SyntaxTextComponent {
101111
match sync::tree_file_content(CWD, item) {
102112
Ok(content) => {
103113
let content = tabs_to_spaces(content);
114+
self.syntax_progress =
115+
Some(ProgressPercent::empty());
104116
self.async_highlighting.spawn(
105117
AsyncSyntaxJob::new(
106118
content.clone(),
@@ -185,16 +197,22 @@ impl DrawableComponent for SyntaxTextComponent {
185197
},
186198
);
187199

200+
let title = format!(
201+
"{}{}",
202+
self.current_file
203+
.as_ref()
204+
.map(|(name, _)| name.clone())
205+
.unwrap_or_default(),
206+
self.syntax_progress
207+
.map(|p| format!(" ({}%)", p.progress))
208+
.unwrap_or_default()
209+
);
210+
188211
let content = StatefulParagraph::new(text)
189212
.wrap(Wrap { trim: false })
190213
.block(
191214
Block::default()
192-
.title(
193-
self.current_file
194-
.as_ref()
195-
.map(|(name, _)| name.clone())
196-
.unwrap_or_default(),
197-
)
215+
.title(title)
198216
.borders(Borders::ALL)
199217
.border_style(self.theme.title(self.focused())),
200218
);

src/main.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,16 @@ pub enum QueueEvent {
7676
InputEvent(InputEvent),
7777
}
7878

79+
#[derive(Clone, Copy, Debug, PartialEq)]
80+
pub enum SyntaxHighlightProgress {
81+
Progress(asyncgit::ProgressPercent),
82+
Done,
83+
}
84+
7985
#[derive(Clone, Copy, Debug, PartialEq)]
8086
pub enum AsyncAppNotification {
8187
///
82-
SyntaxHighlighting,
88+
SyntaxHighlighting(SyntaxHighlightProgress),
8389
}
8490

8591
#[derive(Clone, Copy, Debug, PartialEq)]

0 commit comments

Comments
 (0)