mirror of
https://github.com/gitui-org/gitui
synced 2026-05-23 17:08:21 +00:00
asyncjob supports sending arbitrary notifications
this is used to send progress reports during work on the job
This commit is contained in:
parent
b9e4631ff4
commit
0454e2a1cd
8 changed files with 179 additions and 53 deletions
|
|
@ -12,7 +12,10 @@ pub trait AsyncJob: Send + Sync + Clone {
|
||||||
type Notification: Copy + Send + 'static;
|
type Notification: Copy + Send + 'static;
|
||||||
|
|
||||||
/// can run a synchronous time intensive task
|
/// can run a synchronous time intensive task
|
||||||
fn run(&mut self) -> Self::Notification;
|
fn run(
|
||||||
|
&mut self,
|
||||||
|
sender: Sender<Self::Notification>,
|
||||||
|
) -> Result<Self::Notification>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Abstraction for a FIFO task queue that will only queue up **one** `next` job.
|
/// Abstraction for a FIFO task queue that will only queue up **one** `next` job.
|
||||||
|
|
@ -95,7 +98,7 @@ impl<J: 'static + AsyncJob> AsyncSingleJob<J> {
|
||||||
{
|
{
|
||||||
let _pending = self.pending.lock()?;
|
let _pending = self.pending.lock()?;
|
||||||
|
|
||||||
let notification = task.run();
|
let notification = task.run(self.sender.clone())?;
|
||||||
|
|
||||||
if let Ok(mut last) = self.last.lock() {
|
if let Ok(mut last) = self.last.lock() {
|
||||||
*last = Some(task);
|
*last = Some(task);
|
||||||
|
|
@ -147,7 +150,10 @@ mod test {
|
||||||
impl AsyncJob for TestJob {
|
impl AsyncJob for TestJob {
|
||||||
type Notification = TestNotificaton;
|
type Notification = TestNotificaton;
|
||||||
|
|
||||||
fn run(&mut self) -> Self::Notification {
|
fn run(
|
||||||
|
&mut self,
|
||||||
|
_sender: Sender<Self::Notification>,
|
||||||
|
) -> Result<Self::Notification> {
|
||||||
println!("[job] wait");
|
println!("[job] wait");
|
||||||
|
|
||||||
while !self.finish.load(Ordering::SeqCst) {
|
while !self.finish.load(Ordering::SeqCst) {
|
||||||
|
|
@ -165,7 +171,7 @@ mod test {
|
||||||
|
|
||||||
println!("[job] value: {}", res);
|
println!("[job] value: {}", res);
|
||||||
|
|
||||||
()
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,51 +3,67 @@
|
||||||
use std::{num::TryFromIntError, string::FromUtf8Error};
|
use std::{num::TryFromIntError, string::FromUtf8Error};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
|
///
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
///
|
||||||
#[error("`{0}`")]
|
#[error("`{0}`")]
|
||||||
Generic(String),
|
Generic(String),
|
||||||
|
|
||||||
|
///
|
||||||
#[error("git: no head found")]
|
#[error("git: no head found")]
|
||||||
NoHead,
|
NoHead,
|
||||||
|
|
||||||
|
///
|
||||||
#[error("git: conflict during rebase")]
|
#[error("git: conflict during rebase")]
|
||||||
RebaseConflict,
|
RebaseConflict,
|
||||||
|
|
||||||
|
///
|
||||||
#[error("git: remote url not found")]
|
#[error("git: remote url not found")]
|
||||||
UnknownRemote,
|
UnknownRemote,
|
||||||
|
|
||||||
|
///
|
||||||
#[error("git: inconclusive remotes")]
|
#[error("git: inconclusive remotes")]
|
||||||
NoDefaultRemoteFound,
|
NoDefaultRemoteFound,
|
||||||
|
|
||||||
|
///
|
||||||
#[error("git: work dir error")]
|
#[error("git: work dir error")]
|
||||||
NoWorkDir,
|
NoWorkDir,
|
||||||
|
|
||||||
|
///
|
||||||
#[error("git: uncommitted changes")]
|
#[error("git: uncommitted changes")]
|
||||||
UncommittedChanges,
|
UncommittedChanges,
|
||||||
|
|
||||||
|
///
|
||||||
#[error("git: can\u{2019}t run blame on a binary file")]
|
#[error("git: can\u{2019}t run blame on a binary file")]
|
||||||
NoBlameOnBinaryFile,
|
NoBlameOnBinaryFile,
|
||||||
|
|
||||||
|
///
|
||||||
#[error("binary file")]
|
#[error("binary file")]
|
||||||
BinaryFile,
|
BinaryFile,
|
||||||
|
|
||||||
|
///
|
||||||
#[error("io error:{0}")]
|
#[error("io error:{0}")]
|
||||||
Io(#[from] std::io::Error),
|
Io(#[from] std::io::Error),
|
||||||
|
|
||||||
|
///
|
||||||
#[error("git error:{0}")]
|
#[error("git error:{0}")]
|
||||||
Git(#[from] git2::Error),
|
Git(#[from] git2::Error),
|
||||||
|
|
||||||
|
///
|
||||||
#[error("utf8 error:{0}")]
|
#[error("utf8 error:{0}")]
|
||||||
Utf8Conversion(#[from] FromUtf8Error),
|
Utf8Conversion(#[from] FromUtf8Error),
|
||||||
|
|
||||||
|
///
|
||||||
#[error("TryFromInt error:{0}")]
|
#[error("TryFromInt error:{0}")]
|
||||||
IntConversion(#[from] TryFromIntError),
|
IntConversion(#[from] TryFromIntError),
|
||||||
|
|
||||||
|
///
|
||||||
#[error("EasyCast error:{0}")]
|
#[error("EasyCast error:{0}")]
|
||||||
EasyCast(#[from] easy_cast::Error),
|
EasyCast(#[from] easy_cast::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
pub type Result<T> = std::result::Result<T, Error>;
|
pub type Result<T> = std::result::Result<T, Error>;
|
||||||
|
|
||||||
impl<T> From<std::sync::PoisonError<T>> for Error {
|
impl<T> From<std::sync::PoisonError<T>> for Error {
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,9 @@ pub use crate::{
|
||||||
blame::{AsyncBlame, BlameParams},
|
blame::{AsyncBlame, BlameParams},
|
||||||
commit_files::{AsyncCommitFiles, CommitFilesParams},
|
commit_files::{AsyncCommitFiles, CommitFilesParams},
|
||||||
diff::{AsyncDiff, DiffParams, DiffType},
|
diff::{AsyncDiff, DiffParams, DiffType},
|
||||||
|
error::{Error, Result},
|
||||||
fetch::{AsyncFetch, FetchRequest},
|
fetch::{AsyncFetch, FetchRequest},
|
||||||
|
progress::ProgressPercent,
|
||||||
push::{AsyncPush, PushRequest},
|
push::{AsyncPush, PushRequest},
|
||||||
push_tags::{AsyncPushTags, PushTagsRequest},
|
push_tags::{AsyncPushTags, PushTagsRequest},
|
||||||
remote_progress::{RemoteProgress, RemoteProgressState},
|
remote_progress::{RemoteProgress, RemoteProgressState},
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ use easy_cast::{Conv, ConvFloat};
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
|
|
||||||
///
|
///
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
pub struct ProgressPercent {
|
pub struct ProgressPercent {
|
||||||
/// percent 0..100
|
/// percent 0..100
|
||||||
pub progress: u8,
|
pub progress: u8,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
//!
|
//!
|
||||||
|
|
||||||
|
use crossbeam_channel::Sender;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
asyncjob::AsyncJob,
|
asyncjob::AsyncJob,
|
||||||
error::Result,
|
error::Result,
|
||||||
|
|
@ -52,7 +54,10 @@ impl AsyncRemoteTagsJob {
|
||||||
impl AsyncJob for AsyncRemoteTagsJob {
|
impl AsyncJob for AsyncRemoteTagsJob {
|
||||||
type Notification = AsyncGitNotification;
|
type Notification = AsyncGitNotification;
|
||||||
|
|
||||||
fn run(&mut self) -> Self::Notification {
|
fn run(
|
||||||
|
&mut self,
|
||||||
|
_sender: Sender<Self::Notification>,
|
||||||
|
) -> Result<Self::Notification> {
|
||||||
if let Ok(mut state) = self.state.lock() {
|
if let Ok(mut state) = self.state.lock() {
|
||||||
*state = state.take().map(|state| match state {
|
*state = state.take().map(|state| match state {
|
||||||
JobState::Request(basic_credential) => {
|
JobState::Request(basic_credential) => {
|
||||||
|
|
@ -73,6 +78,6 @@ impl AsyncJob for AsyncRemoteTagsJob {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncGitNotification::RemoteTags
|
Ok(AsyncGitNotification::RemoteTags)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,13 +9,13 @@ use crate::{
|
||||||
self, common_nav, style::SharedTheme, AsyncSyntaxJob,
|
self, common_nav, style::SharedTheme, AsyncSyntaxJob,
|
||||||
ParagraphState, ScrollPos, StatefulParagraph,
|
ParagraphState, ScrollPos, StatefulParagraph,
|
||||||
},
|
},
|
||||||
AsyncAppNotification, AsyncNotification,
|
AsyncAppNotification, AsyncNotification, SyntaxHighlightProgress,
|
||||||
};
|
};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use asyncgit::{
|
use asyncgit::{
|
||||||
asyncjob::AsyncSingleJob,
|
asyncjob::AsyncSingleJob,
|
||||||
sync::{self, TreeFile},
|
sync::{self, TreeFile},
|
||||||
CWD,
|
ProgressPercent, CWD,
|
||||||
};
|
};
|
||||||
use crossbeam_channel::Sender;
|
use crossbeam_channel::Sender;
|
||||||
use crossterm::event::Event;
|
use crossterm::event::Event;
|
||||||
|
|
@ -33,6 +33,7 @@ use tui::{
|
||||||
pub struct SyntaxTextComponent {
|
pub struct SyntaxTextComponent {
|
||||||
current_file: Option<(String, Either<ui::SyntaxText, String>)>,
|
current_file: Option<(String, Either<ui::SyntaxText, String>)>,
|
||||||
async_highlighting: AsyncSingleJob<AsyncSyntaxJob>,
|
async_highlighting: AsyncSingleJob<AsyncSyntaxJob>,
|
||||||
|
syntax_progress: Option<ProgressPercent>,
|
||||||
key_config: SharedKeyConfig,
|
key_config: SharedKeyConfig,
|
||||||
paragraph_state: Cell<ParagraphState>,
|
paragraph_state: Cell<ParagraphState>,
|
||||||
focused: bool,
|
focused: bool,
|
||||||
|
|
@ -48,6 +49,7 @@ impl SyntaxTextComponent {
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
async_highlighting: AsyncSingleJob::new(sender.clone()),
|
async_highlighting: AsyncSingleJob::new(sender.clone()),
|
||||||
|
syntax_progress: None,
|
||||||
current_file: None,
|
current_file: None,
|
||||||
paragraph_state: Cell::new(ParagraphState::default()),
|
paragraph_state: Cell::new(ParagraphState::default()),
|
||||||
focused: false,
|
focused: false,
|
||||||
|
|
@ -58,19 +60,27 @@ impl SyntaxTextComponent {
|
||||||
|
|
||||||
///
|
///
|
||||||
pub fn update(&mut self, ev: AsyncNotification) {
|
pub fn update(&mut self, ev: AsyncNotification) {
|
||||||
if matches!(
|
if let AsyncNotification::App(
|
||||||
ev,
|
AsyncAppNotification::SyntaxHighlighting(progress),
|
||||||
AsyncNotification::App(
|
) = ev
|
||||||
AsyncAppNotification::SyntaxHighlighting
|
{
|
||||||
)
|
match progress {
|
||||||
) {
|
SyntaxHighlightProgress::Progress(progress) => {
|
||||||
if let Some(job) = self.async_highlighting.take_last() {
|
self.syntax_progress = Some(progress);
|
||||||
if let Some((path, content)) =
|
}
|
||||||
self.current_file.as_mut()
|
SyntaxHighlightProgress::Done => {
|
||||||
{
|
self.syntax_progress = None;
|
||||||
if let Some(syntax) = job.result() {
|
if let Some(job) =
|
||||||
if syntax.path() == Path::new(path) {
|
self.async_highlighting.take_last()
|
||||||
*content = Either::Left(syntax);
|
{
|
||||||
|
if let Some((path, content)) =
|
||||||
|
self.current_file.as_mut()
|
||||||
|
{
|
||||||
|
if let Some(syntax) = job.result() {
|
||||||
|
if syntax.path() == Path::new(path) {
|
||||||
|
*content = Either::Left(syntax);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -101,6 +111,8 @@ impl SyntaxTextComponent {
|
||||||
match sync::tree_file_content(CWD, item) {
|
match sync::tree_file_content(CWD, item) {
|
||||||
Ok(content) => {
|
Ok(content) => {
|
||||||
let content = tabs_to_spaces(content);
|
let content = tabs_to_spaces(content);
|
||||||
|
self.syntax_progress =
|
||||||
|
Some(ProgressPercent::empty());
|
||||||
self.async_highlighting.spawn(
|
self.async_highlighting.spawn(
|
||||||
AsyncSyntaxJob::new(
|
AsyncSyntaxJob::new(
|
||||||
content.clone(),
|
content.clone(),
|
||||||
|
|
@ -185,16 +197,22 @@ impl DrawableComponent for SyntaxTextComponent {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let title = format!(
|
||||||
|
"{}{}",
|
||||||
|
self.current_file
|
||||||
|
.as_ref()
|
||||||
|
.map(|(name, _)| name.clone())
|
||||||
|
.unwrap_or_default(),
|
||||||
|
self.syntax_progress
|
||||||
|
.map(|p| format!(" ({}%)", p.progress))
|
||||||
|
.unwrap_or_default()
|
||||||
|
);
|
||||||
|
|
||||||
let content = StatefulParagraph::new(text)
|
let content = StatefulParagraph::new(text)
|
||||||
.wrap(Wrap { trim: false })
|
.wrap(Wrap { trim: false })
|
||||||
.block(
|
.block(
|
||||||
Block::default()
|
Block::default()
|
||||||
.title(
|
.title(title)
|
||||||
self.current_file
|
|
||||||
.as_ref()
|
|
||||||
.map(|(name, _)| name.clone())
|
|
||||||
.unwrap_or_default(),
|
|
||||||
)
|
|
||||||
.borders(Borders::ALL)
|
.borders(Borders::ALL)
|
||||||
.border_style(self.theme.title(self.focused())),
|
.border_style(self.theme.title(self.focused())),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -76,10 +76,16 @@ pub enum QueueEvent {
|
||||||
InputEvent(InputEvent),
|
InputEvent(InputEvent),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
|
pub enum SyntaxHighlightProgress {
|
||||||
|
Progress(asyncgit::ProgressPercent),
|
||||||
|
Done,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
pub enum AsyncAppNotification {
|
pub enum AsyncAppNotification {
|
||||||
///
|
///
|
||||||
SyntaxHighlighting,
|
SyntaxHighlighting(SyntaxHighlightProgress),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
use asyncgit::asyncjob::AsyncJob;
|
use asyncgit::{asyncjob::AsyncJob, ProgressPercent};
|
||||||
|
use crossbeam_channel::Sender;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use scopetime::scope_time;
|
use scopetime::scope_time;
|
||||||
use std::{
|
use std::{
|
||||||
|
|
@ -6,6 +7,7 @@ use std::{
|
||||||
ops::Range,
|
ops::Range,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
use syntect::{
|
use syntect::{
|
||||||
highlighting::{
|
highlighting::{
|
||||||
|
|
@ -16,7 +18,7 @@ use syntect::{
|
||||||
};
|
};
|
||||||
use tui::text::{Span, Spans};
|
use tui::text::{Span, Spans};
|
||||||
|
|
||||||
use crate::AsyncAppNotification;
|
use crate::{AsyncAppNotification, SyntaxHighlightProgress};
|
||||||
|
|
||||||
struct SyntaxLine {
|
struct SyntaxLine {
|
||||||
items: Vec<(Style, usize, Range<usize>)>,
|
items: Vec<(Style, usize, Range<usize>)>,
|
||||||
|
|
@ -34,12 +36,47 @@ lazy_static! {
|
||||||
static ref THEME_SET: ThemeSet = ThemeSet::load_defaults();
|
static ref THEME_SET: ThemeSet = ThemeSet::load_defaults();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct AsyncProgressBuffer {
|
||||||
|
current: usize,
|
||||||
|
total: usize,
|
||||||
|
last_send: Option<Instant>,
|
||||||
|
min_interval: Duration,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsyncProgressBuffer {
|
||||||
|
pub const fn new(total: usize, min_interval: Duration) -> Self {
|
||||||
|
Self {
|
||||||
|
current: 0,
|
||||||
|
total,
|
||||||
|
last_send: None,
|
||||||
|
min_interval,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn send_progress(&mut self) -> ProgressPercent {
|
||||||
|
self.last_send = Some(Instant::now());
|
||||||
|
ProgressPercent::new(self.current, self.total)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update(&mut self, current: usize) -> bool {
|
||||||
|
self.current = current;
|
||||||
|
self.last_send.map_or(true, |last_send| {
|
||||||
|
last_send.elapsed() > self.min_interval
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl SyntaxText {
|
impl SyntaxText {
|
||||||
pub fn new(text: String, file_path: &Path) -> Self {
|
pub fn new(
|
||||||
|
text: String,
|
||||||
|
file_path: &Path,
|
||||||
|
sender: &Sender<AsyncAppNotification>,
|
||||||
|
) -> asyncgit::Result<Self> {
|
||||||
scope_time!("syntax_highlighting");
|
scope_time!("syntax_highlighting");
|
||||||
log::debug!("syntax: {:?}", file_path);
|
log::debug!("syntax: {:?}", file_path);
|
||||||
|
|
||||||
let mut state = {
|
let mut state = {
|
||||||
|
scope_time!("syntax_highlighting.0");
|
||||||
let syntax = file_path
|
let syntax = file_path
|
||||||
.extension()
|
.extension()
|
||||||
.and_then(OsStr::to_str)
|
.and_then(OsStr::to_str)
|
||||||
|
|
@ -66,27 +103,53 @@ impl SyntaxText {
|
||||||
let mut highlight_state =
|
let mut highlight_state =
|
||||||
HighlightState::new(&highlighter, ScopeStack::new());
|
HighlightState::new(&highlighter, ScopeStack::new());
|
||||||
|
|
||||||
for (number, line) in text.lines().enumerate() {
|
{
|
||||||
let ops = state.parse_line(line, &SYNTAX_SET);
|
let total_count = text.lines().count();
|
||||||
let iter = RangedHighlightIterator::new(
|
|
||||||
&mut highlight_state,
|
|
||||||
&ops[..],
|
|
||||||
line,
|
|
||||||
&highlighter,
|
|
||||||
);
|
|
||||||
|
|
||||||
syntax_lines.push(SyntaxLine {
|
let mut buffer = AsyncProgressBuffer::new(
|
||||||
items: iter
|
total_count,
|
||||||
.map(|(style, _, range)| (style, number, range))
|
Duration::from_millis(200),
|
||||||
.collect(),
|
);
|
||||||
});
|
sender.send(AsyncAppNotification::SyntaxHighlighting(
|
||||||
|
SyntaxHighlightProgress::Progress(
|
||||||
|
buffer.send_progress(),
|
||||||
|
),
|
||||||
|
))?;
|
||||||
|
|
||||||
|
for (number, line) in text.lines().enumerate() {
|
||||||
|
let ops = state.parse_line(line, &SYNTAX_SET);
|
||||||
|
let iter = RangedHighlightIterator::new(
|
||||||
|
&mut highlight_state,
|
||||||
|
&ops[..],
|
||||||
|
line,
|
||||||
|
&highlighter,
|
||||||
|
);
|
||||||
|
|
||||||
|
syntax_lines.push(SyntaxLine {
|
||||||
|
items: iter
|
||||||
|
.map(|(style, _, range)| {
|
||||||
|
(style, number, range)
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
});
|
||||||
|
|
||||||
|
if buffer.update(number) {
|
||||||
|
sender.send(
|
||||||
|
AsyncAppNotification::SyntaxHighlighting(
|
||||||
|
SyntaxHighlightProgress::Progress(
|
||||||
|
buffer.send_progress(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Self {
|
Ok(Self {
|
||||||
text,
|
text,
|
||||||
lines: syntax_lines,
|
lines: syntax_lines,
|
||||||
path: file_path.into(),
|
path: file_path.into(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
|
|
@ -179,18 +242,28 @@ impl AsyncSyntaxJob {
|
||||||
impl AsyncJob for AsyncSyntaxJob {
|
impl AsyncJob for AsyncSyntaxJob {
|
||||||
type Notification = AsyncAppNotification;
|
type Notification = AsyncAppNotification;
|
||||||
|
|
||||||
fn run(&mut self) -> Self::Notification {
|
fn run(
|
||||||
if let Ok(mut state) = self.state.lock() {
|
&mut self,
|
||||||
*state = state.take().map(|state| match state {
|
sender: Sender<Self::Notification>,
|
||||||
|
) -> asyncgit::Result<Self::Notification> {
|
||||||
|
let mut state_mutex = self.state.lock()?;
|
||||||
|
|
||||||
|
if let Some(state) = state_mutex.take() {
|
||||||
|
*state_mutex = Some(match state {
|
||||||
JobState::Request((content, path)) => {
|
JobState::Request((content, path)) => {
|
||||||
let syntax =
|
let syntax = SyntaxText::new(
|
||||||
SyntaxText::new(content, Path::new(&path));
|
content,
|
||||||
|
Path::new(&path),
|
||||||
|
&sender,
|
||||||
|
)?;
|
||||||
JobState::Response(syntax)
|
JobState::Response(syntax)
|
||||||
}
|
}
|
||||||
JobState::Response(res) => JobState::Response(res),
|
JobState::Response(res) => JobState::Response(res),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncAppNotification::SyntaxHighlighting
|
Ok(AsyncAppNotification::SyntaxHighlighting(
|
||||||
|
SyntaxHighlightProgress::Done,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue