mirror of
https://github.com/alexpasmantier/television.git
synced 2025-06-07 12:05:34 +00:00
fixing various issues
This commit is contained in:
parent
d0d453fe97
commit
e17cd18d42
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -2673,7 +2673,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "television"
|
||||
version = "0.1.6"
|
||||
version = "0.1.7"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"better-panic",
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "television"
|
||||
version = "0.1.6"
|
||||
version = "0.1.7"
|
||||
edition = "2021"
|
||||
description = "The revolution will be televised."
|
||||
license = "MIT"
|
||||
|
37
TODO.md
37
TODO.md
@ -1,58 +1,53 @@
|
||||
# bugs
|
||||
|
||||
- [x] index out of bounds when resizing the terminal to a very small size
|
||||
- [x] meta previews in cache are not terminal size aware
|
||||
|
||||
# tasks
|
||||
|
||||
- [x] preview navigation
|
||||
- [x] add a way to open the selected file in the default editor (or maybe that
|
||||
should be achieved using pipes?) --> use xargs for that
|
||||
should be achieved using pipes?) --> use xargs for that
|
||||
- [x] maybe filter out image types etc. for now
|
||||
- [x] return selected entry on exit
|
||||
- [x] piping output to another command
|
||||
- [x] piping custom entries from stdin (e.g. `ls | tv`, what bout choosing
|
||||
previewers in that case? Some AUTO mode?)
|
||||
previewers in that case? Some AUTO mode?)
|
||||
- [x] documentation
|
||||
|
||||
## improvements
|
||||
|
||||
- [x] async finder initialization
|
||||
- [x] async finder search
|
||||
- [x] use nucleo for env
|
||||
- [ ] better keymaps
|
||||
- [x] better keymaps
|
||||
- [ ] mutualize placeholder previews in cache (really not a priority)
|
||||
- [x] better abstractions for channels / separation / isolation so that others
|
||||
can contribute new ones easily
|
||||
- [ ] channel selection in the UI (separate menu or top panel or something)
|
||||
can contribute new ones easily
|
||||
- [x] channel selection in the UI (separate menu or top panel or something)
|
||||
- [x] only render highlighted lines that are visible
|
||||
- [x] only ever read a portion of the file for the temp preview
|
||||
- [ ] make layout an attribute of the channel?
|
||||
- [ ] profile using dyn Traits instead of an enum for channels (might degrade performance by storing on the heap)
|
||||
- [x] profile using dyn Traits instead of an enum for channels (might degrade performance by storing on the heap)
|
||||
- [x] I feel like the finder abstraction is a superfluous layer, maybe just use
|
||||
the channel directly?
|
||||
the channel directly?
|
||||
- [x] support for images is implemented but do we really want that in the core?
|
||||
it's quite heavy
|
||||
it's quite heavy
|
||||
- [x] shrink entry names that are too long (from the middle)
|
||||
- [ ] make the preview toggleable
|
||||
|
||||
## feature ideas
|
||||
- [ ] some sort of iterative fuzzy file explorer (preview contents of folders
|
||||
on the right, enter to go in etc.) maybe with mixed previews of files and
|
||||
folders
|
||||
|
||||
- [x] environment variables
|
||||
- [x] aliases
|
||||
- [ ] shell history
|
||||
- [x] text
|
||||
- [ ] text in documents (pdfs, archives, ...) (rga, adapters)
|
||||
https://github.com/jrmuizel/pdf-extract
|
||||
https://github.com/jrmuizel/pdf-extract
|
||||
- [x] fd
|
||||
- [ ] recent directories
|
||||
- [ ] git (commits, branches, status, diff, ...)
|
||||
- [ ] makefile commands
|
||||
- [ ] remote files (s3, ...)
|
||||
- [ ] custom actions as part of a channel (mappable)
|
||||
- [ ] from one set of entries to another? (fuzzy-refine) maybe piping
|
||||
tv with itself?
|
||||
- [ ] add a way of copying the selected entry name/value to the clipboard
|
||||
- [ ] have a keybind to send all current entries to stdout ... oorrrrr to another channel??
|
||||
- [ ] action menu on the bottom: send to channel, copy to clipboard, send to stdout, ... maybe with tab to navigate
|
||||
between possible actions (defined per channel, not all channels can pipe to all channels)
|
||||
- [ ] git repositories channel (crawl the filesystem for git repos)
|
||||
- [x] add a way of copying the selected entry name/value to the clipboard
|
||||
- [ ] have a keybinding to send all current entries to stdout
|
||||
- [x] git repositories channel (crawl the filesystem for git repos)
|
||||
|
@ -1,55 +1,3 @@
|
||||
/**
|
||||
|
||||
The general idea
|
||||
┌──────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ │
|
||||
│ rendering thread event thread main thread │
|
||||
│ │
|
||||
│ │ │ │ │
|
||||
│ │
|
||||
│ │ │ │ │
|
||||
│ │
|
||||
│ │ │ │ │
|
||||
│ ┌───────┴───────┐ │
|
||||
│ │ │ │ │ │
|
||||
│ │ receive event │ │
|
||||
│ │ │ │ │ │
|
||||
│ └───────┬───────┘ │
|
||||
│ │ │ │ │
|
||||
│ ▼ │
|
||||
│ │ ┌──────────────────┐ ┌──────────┴─────────┐ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │send on `event_rx`├────────────►│ receive `event_rx` │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ └──────────────────┘ └──────────┬─────────┘ │
|
||||
│ │ │
|
||||
│ │ ▼ │
|
||||
│ ┌────────────────────┐ │
|
||||
│ │ │ map to action │ │
|
||||
│ └──────────┬─────────┘ │
|
||||
│ │ ▼ │
|
||||
│ ┌────────────────────┐ │
|
||||
│ │ │ send on `action_tx`│ │
|
||||
│ └──────────┬─────────┘ │
|
||||
│ │ │
|
||||
│ │
|
||||
│ │ ┌──────────┴─────────┐ │
|
||||
│ │ receive `action_rx`│ │
|
||||
│ │ └──────────┬─────────┘ │
|
||||
│ ┌───────────┴────────────┐ ▼ │
|
||||
│ │ │ ┌────────────────────┐ │
|
||||
│ │ receive `render_rx` │◄────────────────────────────────────────────────┤ dispatch action │ │
|
||||
│ │ │ └──────────┬─────────┘ │
|
||||
│ └───────────┬────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ ▼ ▼ │
|
||||
│ ┌────────────────────────┐ ┌────────────────────┐ │
|
||||
│ │ render components │ │ update components │ │
|
||||
│ └────────────────────────┘ └────────────────────┘ │
|
||||
│ │
|
||||
└──────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
|
||||
*/
|
||||
use std::sync::Arc;
|
||||
|
||||
use color_eyre::Result;
|
||||
|
@ -1,4 +1,5 @@
|
||||
use devicons::FileIcon;
|
||||
use directories::BaseDirs;
|
||||
use ignore::overrides::OverrideBuilder;
|
||||
use nucleo::{
|
||||
pattern::{CaseMatching, Normalization},
|
||||
@ -36,8 +37,9 @@ impl Channel {
|
||||
None,
|
||||
1,
|
||||
);
|
||||
let base_dirs = BaseDirs::new().unwrap();
|
||||
let crawl_handle = tokio::spawn(crawl_for_repos(
|
||||
std::env::home_dir().expect("Could not get home directory"),
|
||||
base_dirs.home_dir().to_path_buf(),
|
||||
matcher.injector(),
|
||||
));
|
||||
Channel {
|
||||
@ -142,7 +144,9 @@ impl OnAir for Channel {
|
||||
fn get_ignored_paths() -> Vec<PathBuf> {
|
||||
let mut ignored_paths = Vec::new();
|
||||
|
||||
if let Some(home) = std::env::home_dir() {
|
||||
if let Some(base_dirs) = BaseDirs::new() {
|
||||
let home = base_dirs.home_dir();
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
ignored_paths.push(home.join("Library"));
|
||||
@ -207,7 +211,7 @@ async fn crawl_for_repos(
|
||||
// if the entry is a .git directory, add its parent to the list of git repos
|
||||
if entry.path().ends_with(".git") {
|
||||
let parent_path = preprocess_line(
|
||||
&*entry.path().parent().unwrap().to_string_lossy(),
|
||||
&entry.path().parent().unwrap().to_string_lossy(),
|
||||
);
|
||||
debug!("Found git repo: {:?}", parent_path);
|
||||
let _ = injector.push(parent_path, |e, cols| {
|
||||
|
@ -9,7 +9,6 @@ use std::{
|
||||
io::{BufRead, Read, Seek},
|
||||
path::{Path, PathBuf},
|
||||
sync::{atomic::AtomicUsize, Arc},
|
||||
u32,
|
||||
};
|
||||
use tracing::{debug, warn};
|
||||
|
||||
@ -85,7 +84,7 @@ impl Channel {
|
||||
break;
|
||||
}
|
||||
if let Some(injected_lines) =
|
||||
try_inject_lines(injector.clone(), ¤t_dir, &path)
|
||||
try_inject_lines(&injector, ¤t_dir, &path)
|
||||
{
|
||||
lines_in_mem += injected_lines;
|
||||
}
|
||||
@ -298,11 +297,9 @@ async fn crawl_for_candidates(
|
||||
}
|
||||
}
|
||||
// try to inject the lines of the file
|
||||
if let Some(injected_lines) = try_inject_lines(
|
||||
injector.clone(),
|
||||
¤t_dir,
|
||||
entry.path(),
|
||||
) {
|
||||
if let Some(injected_lines) =
|
||||
try_inject_lines(&injector, ¤t_dir, entry.path())
|
||||
{
|
||||
lines_in_mem.fetch_add(
|
||||
injected_lines,
|
||||
std::sync::atomic::Ordering::Relaxed,
|
||||
@ -316,7 +313,7 @@ async fn crawl_for_candidates(
|
||||
}
|
||||
|
||||
fn try_inject_lines(
|
||||
injector: Injector<CandidateLine>,
|
||||
injector: &Injector<CandidateLine>,
|
||||
current_dir: &PathBuf,
|
||||
path: &Path,
|
||||
) -> Option<usize> {
|
||||
@ -353,7 +350,7 @@ fn try_inject_lines(
|
||||
continue;
|
||||
}
|
||||
let candidate = CandidateLine::new(
|
||||
path.strip_prefix(¤t_dir)
|
||||
path.strip_prefix(current_dir)
|
||||
.unwrap_or(path)
|
||||
.to_path_buf(),
|
||||
line,
|
||||
|
@ -26,6 +26,7 @@ pub struct AppConfig {
|
||||
pub config_dir: PathBuf,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Clone, Debug, Default, Deserialize)]
|
||||
pub struct Config {
|
||||
#[allow(clippy::struct_field_names)]
|
||||
|
@ -138,6 +138,7 @@ impl PreviewCache {
|
||||
}
|
||||
|
||||
/// Get the preview for the given key, or insert a new preview if it doesn't exist.
|
||||
#[allow(dead_code)]
|
||||
pub fn get_or_insert<F>(&mut self, key: String, f: F) -> Arc<Preview>
|
||||
where
|
||||
F: FnOnce() -> Preview,
|
||||
|
@ -2,8 +2,8 @@ use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
|
||||
use devicons::FileIcon;
|
||||
use parking_lot::Mutex;
|
||||
use termtree::Tree;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use crate::entry::Entry;
|
||||
|
||||
@ -23,22 +23,18 @@ impl DirectoryPreviewer {
|
||||
}
|
||||
|
||||
pub async fn preview(&mut self, entry: &Entry) -> Arc<Preview> {
|
||||
if let Some(preview) = self.cache.lock().await.get(&entry.name) {
|
||||
if let Some(preview) = self.cache.lock().get(&entry.name) {
|
||||
return preview;
|
||||
}
|
||||
let preview = meta::loading(&entry.name);
|
||||
self.cache
|
||||
.lock()
|
||||
.await
|
||||
.insert(entry.name.clone(), preview.clone());
|
||||
let entry_c = entry.clone();
|
||||
let cache = self.cache.clone();
|
||||
tokio::spawn(async move {
|
||||
let preview = Arc::new(build_tree_preview(&entry_c));
|
||||
cache
|
||||
.lock()
|
||||
.await
|
||||
.insert(entry_c.name.clone(), preview.clone());
|
||||
cache.lock().insert(entry_c.name.clone(), preview.clone());
|
||||
});
|
||||
preview
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
use color_eyre::Result;
|
||||
//use image::{ImageReader, Rgb};
|
||||
//use ratatui_image::picker::Picker;
|
||||
use parking_lot::Mutex;
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader, Read, Seek};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use syntect::{
|
||||
highlighting::{Theme, ThemeSet},
|
||||
@ -53,7 +53,7 @@ impl FilePreviewer {
|
||||
let path_buf = PathBuf::from(&entry.name);
|
||||
|
||||
// do we have a preview in cache for that entry?
|
||||
if let Some(preview) = self.cache.lock().await.get(&entry.name) {
|
||||
if let Some(preview) = self.cache.lock().get(&entry.name) {
|
||||
return preview.clone();
|
||||
}
|
||||
debug!("No preview in cache for {:?}", entry.name);
|
||||
@ -181,7 +181,7 @@ impl FilePreviewer {
|
||||
"Successfully computed highlights for {:?}",
|
||||
entry_c.name
|
||||
);
|
||||
cache.lock().await.insert(
|
||||
cache.lock().insert(
|
||||
entry_c.name.clone(),
|
||||
Arc::new(Preview::new(
|
||||
entry_c.name,
|
||||
@ -242,7 +242,7 @@ impl FilePreviewer {
|
||||
}
|
||||
|
||||
async fn cache_preview(&mut self, key: String, preview: Arc<Preview>) {
|
||||
self.cache.lock().await.insert(key, preview);
|
||||
self.cache.lock().insert(key, preview);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,10 +84,10 @@ pub async fn render(
|
||||
RenderingTask::Render => {
|
||||
let mut television = television.lock().await;
|
||||
if let Ok(size) = tui.size() {
|
||||
// Ratatui uses u16s to encode terminal dimensions and its
|
||||
// Ratatui uses `u16`s to encode terminal dimensions and its
|
||||
// content for each terminal cell is stored linearly in a
|
||||
// buffer with a u16 index which means we can't support
|
||||
// terminal areas larger than u16::MAX.
|
||||
// buffer with a `u16` index which means we can't support
|
||||
// terminal areas larger than `u16::MAX`.
|
||||
if size.width.checked_mul(size.height).is_some() {
|
||||
tui.terminal.draw(|frame| {
|
||||
if let Err(err) = television.draw(frame, frame.area()) {
|
||||
|
@ -86,7 +86,6 @@ impl Television {
|
||||
UnitChannel::from(&self.channel)
|
||||
}
|
||||
|
||||
/// FIXME: this needs rework
|
||||
pub fn change_channel(&mut self, channel: TelevisionChannel) {
|
||||
self.reset_preview_scroll();
|
||||
self.reset_picker_selection();
|
||||
@ -362,15 +361,6 @@ impl Television {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn reset_screen(&mut self) {
|
||||
self.reset_preview_scroll();
|
||||
self.reset_picker_selection();
|
||||
self.reset_picker_input();
|
||||
self.current_pattern = EMPTY_STRING.to_string();
|
||||
self.channel.find(EMPTY_STRING);
|
||||
self.remote_control.find(EMPTY_STRING);
|
||||
}
|
||||
|
||||
/// Render the television on the screen.
|
||||
///
|
||||
/// # Arguments
|
||||
|
@ -1,4 +1,4 @@
|
||||
use ratatui::style::{Color, Style};
|
||||
use ratatui::style::Color;
|
||||
|
||||
pub(crate) mod help;
|
||||
pub mod input;
|
||||
@ -11,24 +11,5 @@ pub mod preview;
|
||||
mod remote_control;
|
||||
pub mod results;
|
||||
pub mod spinner;
|
||||
// input
|
||||
//const DEFAULT_INPUT_FG: Color = Color::Rgb(200, 200, 200);
|
||||
//const DEFAULT_RESULTS_COUNT_FG: Color = Color::Rgb(150, 150, 150);
|
||||
// preview
|
||||
//const DEFAULT_PREVIEW_TITLE_FG: Color = Color::Blue;
|
||||
//const DEFAULT_SELECTED_PREVIEW_BG: Color = Color::Rgb(50, 50, 50);
|
||||
//const DEFAULT_PREVIEW_CONTENT_FG: Color = Color::Rgb(150, 150, 180);
|
||||
//const DEFAULT_PREVIEW_GUTTER_FG: Color = Color::Rgb(70, 70, 70);
|
||||
//const DEFAULT_PREVIEW_GUTTER_SELECTED_FG: Color = Color::Rgb(255, 150, 150);
|
||||
|
||||
pub fn get_border_style(focused: bool) -> Style {
|
||||
Style::default().fg(Color::Blue)
|
||||
|
||||
// NOTE: do we want to change the border color based on focus? Are we
|
||||
// keeping the focus feature at all?
|
||||
// if focused {
|
||||
// Style::default().fg(Color::Green)
|
||||
// } else {
|
||||
// Style::default().fg(Color::Blue)
|
||||
// }
|
||||
}
|
||||
pub const BORDER_COLOR: Color = Color::Blue;
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::channels::OnAir;
|
||||
use crate::television::Television;
|
||||
use crate::ui::get_border_style;
|
||||
use crate::ui::layout::Layout;
|
||||
use crate::ui::BORDER_COLOR;
|
||||
use color_eyre::eyre::Result;
|
||||
use ratatui::layout::{
|
||||
Alignment, Constraint, Direction, Layout as RatatuiLayout,
|
||||
@ -422,7 +422,7 @@ impl Television {
|
||||
.title_top(Line::from(" Pattern ").alignment(Alignment::Center))
|
||||
.borders(Borders::ALL)
|
||||
.border_type(BorderType::Rounded)
|
||||
.border_style(get_border_style(false))
|
||||
.border_style(Style::default().fg(BORDER_COLOR))
|
||||
.style(Style::default());
|
||||
|
||||
let input_block_inner = input_block.inner(layout.input);
|
||||
|
@ -3,7 +3,7 @@ use crate::previewers::{
|
||||
Preview, PreviewContent, FILE_TOO_LARGE_MSG, PREVIEW_NOT_SUPPORTED_MSG,
|
||||
};
|
||||
use crate::television::Television;
|
||||
use crate::ui::get_border_style;
|
||||
use crate::ui::BORDER_COLOR;
|
||||
use crate::ui::layout::Layout;
|
||||
use crate::utils::strings::{shrink_with_ellipsis, EMPTY_STRING};
|
||||
use color_eyre::eyre::Result;
|
||||
@ -55,7 +55,7 @@ impl Television {
|
||||
Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.border_type(BorderType::Rounded)
|
||||
.border_style(get_border_style(false)),
|
||||
.border_style(Style::default().fg(BORDER_COLOR)),
|
||||
)
|
||||
.alignment(Alignment::Left);
|
||||
f.render_widget(preview_title, layout.preview_title);
|
||||
@ -73,7 +73,7 @@ impl Television {
|
||||
.title_top(Line::from(" Preview ").alignment(Alignment::Center))
|
||||
.borders(Borders::ALL)
|
||||
.border_type(BorderType::Rounded)
|
||||
.border_style(get_border_style(false))
|
||||
.border_style(Style::default().fg(BORDER_COLOR))
|
||||
.style(Style::default())
|
||||
.padding(Padding::right(1));
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::channels::OnAir;
|
||||
use crate::television::Television;
|
||||
use crate::ui::get_border_style;
|
||||
use crate::ui::BORDER_COLOR;
|
||||
use crate::ui::logo::build_remote_logo_paragraph;
|
||||
use crate::ui::mode::mode_color;
|
||||
use crate::ui::results::{build_results_list, ResultsListColors};
|
||||
@ -41,7 +41,7 @@ impl Television {
|
||||
let rc_block = Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.border_type(BorderType::Rounded)
|
||||
.border_style(get_border_style(false))
|
||||
.border_style(Style::default().fg(BORDER_COLOR))
|
||||
.style(Style::default())
|
||||
.padding(Padding::right(1));
|
||||
|
||||
@ -81,7 +81,7 @@ impl Television {
|
||||
)
|
||||
.borders(Borders::ALL)
|
||||
.border_type(BorderType::Rounded)
|
||||
.border_style(get_border_style(false))
|
||||
.border_style(Style::default().fg(BORDER_COLOR))
|
||||
.style(Style::default());
|
||||
|
||||
let input_block_inner = input_block.inner(*area);
|
||||
|
@ -1,12 +1,12 @@
|
||||
use crate::channels::OnAir;
|
||||
use crate::entry::Entry;
|
||||
use crate::television::Television;
|
||||
use crate::ui::get_border_style;
|
||||
use crate::ui::layout::Layout;
|
||||
use crate::ui::BORDER_COLOR;
|
||||
use crate::utils::strings::{next_char_boundary, slice_at_char_boundaries};
|
||||
use color_eyre::eyre::Result;
|
||||
use ratatui::layout::Alignment;
|
||||
use ratatui::prelude::{Color, Line, Span, Style, Stylize};
|
||||
use ratatui::prelude::{Color, Line, Span, Style};
|
||||
use ratatui::widgets::{
|
||||
Block, BorderType, Borders, List, ListDirection, Padding,
|
||||
};
|
||||
@ -37,6 +37,7 @@ impl Default for ResultsListColors {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl ResultsListColors {
|
||||
pub fn result_name_fg(mut self, color: Color) -> Self {
|
||||
self.result_name_fg = color;
|
||||
@ -179,7 +180,7 @@ impl Television {
|
||||
.title_top(Line::from(" Results ").alignment(Alignment::Center))
|
||||
.borders(Borders::ALL)
|
||||
.border_type(BorderType::Rounded)
|
||||
.border_style(get_border_style(false))
|
||||
.border_style(Style::default().fg(BORDER_COLOR))
|
||||
.style(Style::default())
|
||||
.padding(Padding::right(1));
|
||||
|
||||
|
@ -71,10 +71,6 @@ pub fn is_not_text(bytes: &[u8]) -> Option<bool> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_valid_utf8(bytes: &[u8]) -> bool {
|
||||
std::str::from_utf8(bytes).is_ok()
|
||||
}
|
||||
|
||||
pub fn is_known_text_extension(path: &Path) -> bool {
|
||||
path.extension()
|
||||
.and_then(|ext| ext.to_str())
|
||||
|
@ -68,7 +68,7 @@ const NULL_CHARACTER: char = '\x00';
|
||||
const UNIT_SEPARATOR_CHARACTER: char = '\u{001F}';
|
||||
const APPLICATION_PROGRAM_COMMAND_CHARACTER: char = '\u{009F}';
|
||||
|
||||
pub fn replace_nonprintable(input: &[u8], tab_width: usize) -> String {
|
||||
pub fn replace_non_printable(input: &[u8], tab_width: usize) -> String {
|
||||
let mut output = String::new();
|
||||
|
||||
let mut idx = 0;
|
||||
@ -130,7 +130,7 @@ pub fn proportion_of_printable_ascii_characters(buffer: &[u8]) -> f32 {
|
||||
const MAX_LINE_LENGTH: usize = 300;
|
||||
|
||||
pub fn preprocess_line(line: &str) -> String {
|
||||
replace_nonprintable(
|
||||
replace_non_printable(
|
||||
{
|
||||
if line.len() > MAX_LINE_LENGTH {
|
||||
slice_up_to_char_boundary(line, MAX_LINE_LENGTH)
|
||||
@ -160,48 +160,48 @@ pub fn shrink_with_ellipsis(s: &str, max_length: usize) -> String {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
fn test_replace_nonprintable(input: &str, expected: &str) {
|
||||
let actual = replace_nonprintable(input.as_bytes(), 2);
|
||||
fn test_replace_non_printable(input: &str, expected: &str) {
|
||||
let actual = replace_non_printable(input.as_bytes(), 2);
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_replace_nonprintable_ascii() {
|
||||
test_replace_nonprintable("Hello, World!", "Hello, World!");
|
||||
fn test_replace_non_printable_ascii() {
|
||||
test_replace_non_printable("Hello, World!", "Hello, World!");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_replace_nonprintable_tab() {
|
||||
test_replace_nonprintable("Hello\tWorld!", "Hello World!");
|
||||
test_replace_nonprintable(
|
||||
fn test_replace_non_printable_tab() {
|
||||
test_replace_non_printable("Hello\tWorld!", "Hello World!");
|
||||
test_replace_non_printable(
|
||||
" -- AND
|
||||
", " -- AND",
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_replace_nonprintable_line_feed() {
|
||||
test_replace_nonprintable("Hello\nWorld!", "HelloWorld!");
|
||||
fn test_replace_non_printable_line_feed() {
|
||||
test_replace_non_printable("Hello\nWorld!", "HelloWorld!");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_replace_nonprintable_null() {
|
||||
test_replace_nonprintable("Hello\x00World!", "Hello␀World!");
|
||||
test_replace_nonprintable("Hello World!\0", "Hello World!␀");
|
||||
fn test_replace_non_printable_null() {
|
||||
test_replace_non_printable("Hello\x00World!", "Hello␀World!");
|
||||
test_replace_non_printable("Hello World!\0", "Hello World!␀");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_replace_nonprintable_delete() {
|
||||
test_replace_nonprintable("Hello\x7FWorld!", "Hello␀World!");
|
||||
fn test_replace_non_printable_delete() {
|
||||
test_replace_non_printable("Hello\x7FWorld!", "Hello␀World!");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_replace_nonprintable_bom() {
|
||||
test_replace_nonprintable("Hello\u{FEFF}World!", "HelloWorld!");
|
||||
fn test_replace_non_printable_bom() {
|
||||
test_replace_non_printable("Hello\u{FEFF}World!", "HelloWorld!");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_replace_nonprintable_start_txt() {
|
||||
test_replace_nonprintable("Àì", "Àì␀");
|
||||
fn test_replace_non_printable_start_txt() {
|
||||
test_replace_non_printable("Àì", "Àì␀");
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ pub fn compute_highlights_for_path(
|
||||
Ok(highlighted_lines)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn compute_highlights_for_line<'a>(
|
||||
line: &'a str,
|
||||
syntax_set: &SyntaxSet,
|
||||
|
Loading…
x
Reference in New Issue
Block a user