Skip to content

Commit

Permalink
kewl progress
Browse files Browse the repository at this point in the history
  • Loading branch information
alexpasmantier committed Sep 21, 2024
1 parent f56ba58 commit f38c8d9
Show file tree
Hide file tree
Showing 22 changed files with 1,490 additions and 40 deletions.
9 changes: 8 additions & 1 deletion .config/config.json5
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,16 @@
"keybindings": {
"Input": {
"<q>": "Quit", // Quit the application
"<esc>": "Quit", // Quit the application
"<ctrl-d>": "Quit", // Another way to quit
"<ctrl-c>": "Quit", // Yet another way to quit
"<Ctrl-z>": "Suspend", // Suspend the application
"<ctrl-z>": "Suspend", // Suspend the application
"<tab>": "GoToNextPane", // Move to the next pane
"<backtab>": "GoToPreviousPane", // Move to the previous pane
"<ctrl-up>": "GoToPaneUp", // Move to the pane above
"<ctrl-down>": "GoToPaneDown", // Move to the pane below
"<ctrl-left>": "GoToPaneLeft", // Move to the pane to the left
"<ctrl-right>": "GoToPaneRight", // Move to the pane to the right
},
}
}
20 changes: 20 additions & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,14 @@ crossterm = { version = "0.28.1", features = ["serde", "event-stream"] }
derive_deref = "1.1.1"
directories = "5.0.1"
futures = "0.3.30"
fuzzy-matcher = "0.3.7"
human-panic = "2.0.1"
json5 = "0.4.1"
lazy_static = "1.5.0"
libc = "0.2.158"
pretty_assertions = "1.4.0"
ratatui = { version = "0.28.1", features = ["serde", "macros"] }
rust-devicons = "0.2.2"
serde = { version = "1.0.208", features = ["derive"] }
serde_json = "1.0.125"
signal-hook = "0.3.17"
Expand Down
2 changes: 2 additions & 0 deletions src/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ pub enum Action {
GoToPaneDown,
GoToPaneLeft,
GoToPaneRight,
GoToNextPane,
GoToPreviousPane,
ScrollPreviewUp,
ScrollPreviewDown,
ScrollPreviewHalfPageUp,
Expand Down
85 changes: 53 additions & 32 deletions src/app.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,52 @@
/// Rendering thread Event thread Main thread
///
/// ┌─────────────────┐
/// │ get key event │
/// └─────────────────┘
/// │
/// ▼
/// ┌─────────────────┐
/// │ map event to │
/// │ action │
/// └─────────────────┘
/// │
/// ▼
/// ┌──────────────────────────┐ ┌─────────────────┐
/// │ send action on action_tx │ ─────▶ │ Recv action │
/// └──────────────────────────┘ └─────────────────┘
/// │
/// ▼
/// ┌───────────────────┐ ┌─────────────────┐
/// │ Recv on render_rx │ ◀────────────────────────────────────── │ Dispatch action │
/// └───────────────────┘ └─────────────────┘
/// │ │
/// ▼ ▼
/// ┌──────────────────┐ ┌──────────────────┐
/// │ Render component │ │ Update component │
/// └──────────────────┘ └──────────────────┘
///
/// 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, Mutex};

use color_eyre::Result;
Expand All @@ -34,7 +56,8 @@ use tracing::debug;

use crate::{
action::Action,
components::{fps::FpsCounter, home::Home, Component},
cli::TvChannel,
components::{television::Television, Component},
config::Config,
event::{Event, EventLoop, Key},
render::{render, RenderingTask},
Expand Down Expand Up @@ -68,18 +91,16 @@ pub enum Mode {
}

impl App {
pub fn new(tick_rate: f64, frame_rate: f64) -> Result<Self> {
pub fn new(channel: TvChannel, tick_rate: f64, frame_rate: f64) -> Result<Self> {
let (action_tx, action_rx) = mpsc::unbounded_channel();
let (render_tx, _) = mpsc::unbounded_channel();
let event_loop = EventLoop::new(tick_rate, true);
let television = Television::new(channel);

Ok(Self {
tick_rate,
frame_rate,
components: Arc::new(Mutex::new(vec![
Box::new(Home::new()),
Box::new(FpsCounter::default()),
])),
components: Arc::new(Mutex::new(vec![Box::new(television)])),
should_quit: false,
should_suspend: false,
config: Config::new()?,
Expand Down
15 changes: 13 additions & 2 deletions src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
use clap::Parser;
use clap::{Parser, ValueEnum};

use crate::config::{get_config_dir, get_data_dir};

#[derive(Clone, ValueEnum, Debug, Default)]
pub enum TvChannel {
#[default]
ENV,
OTHER,
}

#[derive(Parser, Debug)]
#[command(author, version = version(), about)]
pub struct Cli {
/// Which channel shall we watch?
#[arg(value_enum)]
pub channel: TvChannel,

/// Tick rate, i.e. number of ticks per second
#[arg(short, long, value_name = "FLOAT", default_value_t = 8.0)]
#[arg(short, long, value_name = "FLOAT", default_value_t = 20.0)]
pub tick_rate: f64,

/// Frame rate, i.e. number of frames per second
Expand Down
8 changes: 8 additions & 0 deletions src/components.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,16 @@ use tokio::sync::mpsc::UnboundedSender;

use crate::{action::Action, config::Config};

mod display;
mod finders;
pub mod fps;
pub mod home;
mod input;
mod pickers;
mod previewers;
mod sorters;
pub mod television;
mod utils;

/// `Component` is a trait that represents a visual and interactive element of the user interface.
///
Expand Down
17 changes: 17 additions & 0 deletions src/components/display.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/// This module contains abstract display logic for the application.
/// A group of styles that can be applied to a string.
pub enum StyleGroup {
Default,
Entry,
EntryLineNumber,
EntryContent,
}

/// A styled string with a text and a style group for that string.
/// This is used to produce styled output in a way that can then be translated to the actual
/// frontend implementation.
pub struct StyledString {
pub text: String,
pub style: StyleGroup,
}
25 changes: 25 additions & 0 deletions src/components/finders.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
mod env;

// finder types
pub use env::EnvVarFinder;
use rust_devicons::FileIcon;

#[derive(Clone, Debug)]
pub struct Entry {
pub name: String,
pub preview: Option<String>,
pub score: i64,
pub name_match_ranges: Option<Vec<(usize, usize)>>,
pub preview_match_ranges: Option<Vec<(usize, usize)>>,
pub icon: Option<FileIcon>,
pub line_number: Option<usize>,
}

/// A trait for a finder that can find entries based on a pattern.
/// The `find` method takes a pattern and returns an iterator over the entries found.
///
/// # Methods
/// - `find`: Find entries based on a pattern.
pub trait Finder {
fn find(&self, pattern: &str) -> impl Iterator<Item = Entry>;
}
81 changes: 81 additions & 0 deletions src/components/finders/env.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
use std::{env::vars, path::Path};

use fuzzy_matcher::skim::SkimMatcherV2;
use rust_devicons::{icon_for_file, File, FileIcon};

use crate::components::finders::{Entry, Finder};

struct EnvVar {
name: String,
value: String,
}

pub struct EnvVarFinder {
env_vars: Vec<EnvVar>,
matcher: SkimMatcherV2,
file_icon: FileIcon,
}

impl EnvVarFinder {
pub fn new() -> Self {
let mut env_vars = Vec::new();
for (name, value) in vars() {
env_vars.push(EnvVar { name, value });
}
let file_icon = icon_for_file(&File::new(&Path::new("config")), None);
EnvVarFinder {
env_vars,
matcher: SkimMatcherV2::default(),
file_icon,
}
}
}

impl Finder for EnvVarFinder {
fn find(&self, pattern: &str) -> impl Iterator<Item = Entry> {
let mut results = Vec::new();
for env_var in &self.env_vars {
if pattern.is_empty() {
results.push(Entry {
name: env_var.name.clone(),
preview: Some(env_var.value.clone()),
score: 0,
name_match_ranges: None,
preview_match_ranges: None,
icon: Some(self.file_icon.clone()),
line_number: None,
});
} else {
let mut total_score = 0;
let preview_match_ranges = if let Some((score, indices)) =
self.matcher.fuzzy(&env_var.value, pattern, true)
{
total_score += score;
Some(indices.iter().map(|i| (*i, *i + 1)).collect())
} else {
None
};
let name_match_ranges = if let Some((score, indices)) =
self.matcher.fuzzy(&env_var.name, pattern, true)
{
total_score += score;
Some(indices.iter().map(|i| (*i, *i + 1)).collect())
} else {
None
};
if preview_match_ranges.is_some() || name_match_ranges.is_some() {
results.push(Entry {
name: env_var.name.clone(),
preview: Some(env_var.value.clone()),
score: total_score,
name_match_ranges,
preview_match_ranges,
icon: Some(self.file_icon.clone()),
line_number: None,
});
}
}
}
results.into_iter()
}
}
Loading

0 comments on commit f38c8d9

Please sign in to comment.