Skip to content

Commit

Permalink
perf(preview): add partial preview rendering and buffer preview reque…
Browse files Browse the repository at this point in the history
…sts (#285)
  • Loading branch information
alexpasmantier authored Jan 19, 2025
1 parent c227b2a commit a3dc819
Show file tree
Hide file tree
Showing 19 changed files with 723 additions and 244 deletions.
51 changes: 28 additions & 23 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,14 @@ readme = "README.md"

[workspace.dependencies]
directories = "5.0.1"
devicons = "0.6.11"
color-eyre = "0.6.3"
lazy_static = "1.5.0"
tokio = { version = "1.41.1", features = ["full"] }
tracing = "0.1.40"
tracing-subscriber = { version = "0.3.18", features = ["env-filter", "serde"] }
rustc-hash = "2.1.0"
syntect = "5.2.0"
syntect = {version = "5.2.0", default-features = false, features = ["default-fancy"]}
unicode-width = "0.2.0"
clap = { version = "4.5.20", features = ["derive", "cargo", "string"] }
serde = { version = "1.0.214", features = ["derive"] }
Expand Down Expand Up @@ -104,7 +105,7 @@ copypasta = "0.10.1"

[dev-dependencies]
criterion = "0.5.1"
devicons = "0.6.11"
devicons = { workspace = true }

[[bin]]
bench = false
Expand Down
2 changes: 1 addition & 1 deletion crates/television-channels/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ television-derive = { path = "../television-derive", version = "0.0.21" }
tracing = { workspace = true }
tokio = { workspace = true, features = ["rt"] }
clap = { workspace = true, features = ["derive"] }
devicons = { workspace = true }
directories = { workspace = true }
color-eyre = { workspace = true }
serde = { workspace = true }
lazy_static = { workspace = true }
toml = { workspace = true }
rustc-hash = { workspace = true }

devicons = "0.6.11"
ignore = "0.4.23"
strum = { version = "0.26.3", features = ["derive"] }
regex = "1.11.1"
Expand Down
2 changes: 1 addition & 1 deletion crates/television-previewers/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ television-channels = { path = "../television-channels", version = "0.0.21" }
television-utils = { path = "../television-utils", version = "0.0.21" }

syntect = { workspace = true }
devicons = { workspace = true }
tracing = { workspace = true }
tokio = { workspace = true }
color-eyre = { workspace = true }
lazy_static = { workspace = true }
rustc-hash = { workspace = true }

parking_lot = "0.12.3"
devicons = "0.6.11"
regex = "1.11.1"
nom = "7.1"
tui = { version = "0.29", default-features = false, package = "ratatui" }
Expand Down
87 changes: 68 additions & 19 deletions crates/television-previewers/src/previewers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,44 @@ pub use env::EnvVarPreviewer;
pub use env::EnvVarPreviewerConfig;
pub use files::FilePreviewer;
pub use files::FilePreviewerConfig;
use syntect::highlighting::Style;
use television_utils::cache::RingSet;
use television_utils::syntax::HighlightedLines;

#[derive(Clone, Debug)]
pub enum PreviewContent {
Empty,
FileTooLarge,
SyntectHighlightedText(Vec<Vec<(Style, String)>>),
SyntectHighlightedText(HighlightedLines),
Loading,
Timeout,
NotSupported,
PlainText(Vec<String>),
PlainTextWrapped(String),
AnsiText(String),
}

impl PreviewContent {
pub fn total_lines(&self) -> u16 {
match self {
PreviewContent::SyntectHighlightedText(hl_lines) => {
hl_lines.lines.len().try_into().unwrap_or(u16::MAX)
}
PreviewContent::PlainText(lines) => {
lines.len().try_into().unwrap_or(u16::MAX)
}
PreviewContent::AnsiText(text) => {
text.lines().count().try_into().unwrap_or(u16::MAX)
}
_ => 0,
}
}
}

pub const PREVIEW_NOT_SUPPORTED_MSG: &str =
"Preview for this file type is not supported";
pub const FILE_TOO_LARGE_MSG: &str = "File too large";
pub const LOADING_MSG: &str = "Loading...";
pub const TIMEOUT_MSG: &str = "Preview timed out";

/// A preview of an entry.
///
Expand All @@ -47,7 +68,10 @@ pub struct Preview {
pub title: String,
pub content: PreviewContent,
pub icon: Option<FileIcon>,
pub stale: bool,
/// If the preview is partial, this field contains the byte offset
/// up to which the preview holds.
pub partial_offset: Option<usize>,
pub total_lines: u16,
}

impl Default for Preview {
Expand All @@ -56,7 +80,8 @@ impl Default for Preview {
title: String::new(),
content: PreviewContent::Empty,
icon: None,
stale: false,
partial_offset: None,
total_lines: 0,
}
}
}
Expand All @@ -66,27 +91,22 @@ impl Preview {
title: String,
content: PreviewContent,
icon: Option<FileIcon>,
stale: bool,
partial_offset: Option<usize>,
total_lines: u16,
) -> Self {
Preview {
title,
content,
icon,
stale,
}
}

pub fn stale(&self) -> Self {
Preview {
stale: true,
..self.clone()
partial_offset,
total_lines,
}
}

pub fn total_lines(&self) -> u16 {
match &self.content {
PreviewContent::SyntectHighlightedText(lines) => {
lines.len().try_into().unwrap_or(u16::MAX)
PreviewContent::SyntectHighlightedText(hl_lines) => {
hl_lines.lines.len().try_into().unwrap_or(u16::MAX)
}
PreviewContent::PlainText(lines) => {
lines.len().try_into().unwrap_or(u16::MAX)
Expand All @@ -105,6 +125,7 @@ pub struct Previewer {
file: FilePreviewer,
env_var: EnvVarPreviewer,
command: CommandPreviewer,
requests: RingSet<Entry>,
}

#[derive(Debug, Default)]
Expand Down Expand Up @@ -132,6 +153,8 @@ impl PreviewerConfig {
}
}

const REQUEST_STACK_SIZE: usize = 20;

impl Previewer {
pub fn new(config: Option<PreviewerConfig>) -> Self {
let config = config.unwrap_or_default();
Expand All @@ -140,17 +163,43 @@ impl Previewer {
file: FilePreviewer::new(Some(config.file)),
env_var: EnvVarPreviewer::new(Some(config.env_var)),
command: CommandPreviewer::new(Some(config.command)),
requests: RingSet::with_capacity(REQUEST_STACK_SIZE),
}
}

pub fn preview(&mut self, entry: &Entry) -> Arc<Preview> {
fn dispatch_request(&mut self, entry: &Entry) -> Option<Arc<Preview>> {
match &entry.preview_type {
PreviewType::Basic => self.basic.preview(entry),
PreviewType::EnvVar => self.env_var.preview(entry),
PreviewType::Basic => Some(self.basic.preview(entry)),
PreviewType::EnvVar => Some(self.env_var.preview(entry)),
PreviewType::Files => self.file.preview(entry),
PreviewType::Command(cmd) => self.command.preview(entry, cmd),
PreviewType::None => Arc::new(Preview::default()),
PreviewType::None => Some(Arc::new(Preview::default())),
}
}

fn cached(&self, entry: &Entry) -> Option<Arc<Preview>> {
match &entry.preview_type {
PreviewType::Files => self.file.cached(entry),
PreviewType::Command(_) => self.command.cached(entry),
PreviewType::Basic | PreviewType::EnvVar => None,
PreviewType::None => Some(Arc::new(Preview::default())),
}
}

pub fn preview(&mut self, entry: &Entry) -> Option<Arc<Preview>> {
// if we haven't acknowledged the request yet, acknowledge it
self.requests.push(entry.clone());

if let Some(preview) = self.dispatch_request(entry) {
return Some(preview);
}
// lookup request stack and return the most recent preview available
for request in self.requests.back_to_front() {
if let Some(preview) = self.cached(&request) {
return Some(preview);
}
}
None
}

pub fn set_config(&mut self, config: PreviewerConfig) {
Expand Down
3 changes: 2 additions & 1 deletion crates/television-previewers/src/previewers/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ impl BasicPreviewer {
title: entry.name.clone(),
content: PreviewContent::PlainTextWrapped(entry.name.clone()),
icon: entry.icon,
..Default::default()
partial_offset: None,
total_lines: 1,
})
}
}
Loading

0 comments on commit a3dc819

Please sign in to comment.