refactor: Move project logic into single submodule
This commit is contained in:
parent
4ea4644b90
commit
005b80fc58
42
src/cli.rs
42
src/cli.rs
@ -3,8 +3,8 @@ use std::path::{self, Path, PathBuf};
|
||||
use anyhow::{ensure, Result};
|
||||
use clap::Subcommand;
|
||||
|
||||
use crate::state::write_projects_file;
|
||||
use crate::{dirs, Project, Projects};
|
||||
use crate::dirs;
|
||||
use crate::projects::{write_projects_file, Project, Projects};
|
||||
|
||||
|
||||
#[derive(Debug, Clone, clap::ValueEnum)]
|
||||
@ -81,13 +81,13 @@ where
|
||||
let project = Project::from(path);
|
||||
|
||||
ensure!(
|
||||
!projects.list.contains(&project),
|
||||
!projects.list().contains(&project),
|
||||
"Project path already registered"
|
||||
);
|
||||
|
||||
projects.list.push(project);
|
||||
projects.add(project);
|
||||
write_projects_file(projects)?;
|
||||
println!("Added {}", projects.list.last().unwrap().path().display());
|
||||
println!("Added {}", projects.list().last().unwrap().path().display());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -101,23 +101,22 @@ where
|
||||
let project = Project::from(path);
|
||||
|
||||
ensure!(
|
||||
projects.list.contains(&project),
|
||||
projects.list().contains(&project),
|
||||
"Project path not in registry"
|
||||
);
|
||||
|
||||
let idx =
|
||||
projects.list.iter().enumerate().find_map(
|
||||
|(idx, elem)| {
|
||||
if elem == &project {
|
||||
Some(idx)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
);
|
||||
let idx = projects.iter().enumerate().find_map(
|
||||
|(idx, elem)| {
|
||||
if elem == &project {
|
||||
Some(idx)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
if let Some(idx) = idx {
|
||||
let proj = projects.list.remove(idx);
|
||||
let proj = projects.remove(idx);
|
||||
write_projects_file(projects)?;
|
||||
println!("Removed {}", proj.path().display());
|
||||
}
|
||||
@ -127,8 +126,13 @@ where
|
||||
|
||||
|
||||
fn list_projects(projects: &Projects) -> Result<()> {
|
||||
for (idx, project) in projects.list.iter().enumerate() {
|
||||
println!("{}: {} ({})", idx + 1, project.name(), project.path().display())
|
||||
for (idx, project) in projects.iter().enumerate() {
|
||||
println!(
|
||||
"{}: {} ({})",
|
||||
idx + 1,
|
||||
project.name(),
|
||||
project.path().display()
|
||||
)
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
35
src/main.rs
35
src/main.rs
@ -1,15 +1,13 @@
|
||||
mod cli;
|
||||
mod dirs;
|
||||
mod state;
|
||||
mod projects;
|
||||
mod tui;
|
||||
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use anyhow::Result;
|
||||
use clap::Parser;
|
||||
use cli::Command;
|
||||
use state::read_projects_file;
|
||||
use projects::read_projects_file;
|
||||
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
@ -19,35 +17,6 @@ struct Args {
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, Default, serde::Serialize, serde::Deserialize)]
|
||||
struct Projects {
|
||||
pub list: Vec<Project>,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||
struct Project {
|
||||
path: PathBuf,
|
||||
}
|
||||
|
||||
impl Project {
|
||||
pub fn path(&self) -> &PathBuf {
|
||||
&self.path
|
||||
}
|
||||
|
||||
pub fn name(&self) -> String {
|
||||
let name = self.path.file_name().unwrap();
|
||||
name.to_string_lossy().to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PathBuf> for Project {
|
||||
fn from(path: PathBuf) -> Self {
|
||||
Self { path }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn main() -> Result<()> {
|
||||
init_tracing()?;
|
||||
|
||||
|
@ -1,9 +1,75 @@
|
||||
mod v1;
|
||||
|
||||
use std::fs;
|
||||
use std::io::Write;
|
||||
|
||||
use anyhow::Result;
|
||||
pub use v1::Project;
|
||||
|
||||
use crate::{dirs, Project, Projects};
|
||||
use crate::dirs;
|
||||
|
||||
|
||||
#[derive(Debug, Default, serde::Serialize, serde::Deserialize)]
|
||||
pub struct Projects {
|
||||
list: Vec<Project>,
|
||||
}
|
||||
|
||||
impl Projects {
|
||||
pub fn iter(&self) -> std::slice::Iter<'_, Project> {
|
||||
self.list.iter()
|
||||
}
|
||||
|
||||
pub fn list(&self) -> &[Project] {
|
||||
&self.list
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, idx: usize) -> Project {
|
||||
self.list.remove(idx)
|
||||
}
|
||||
|
||||
pub fn add(&mut self, project: Project) {
|
||||
self.list.push(project);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'a> IntoIterator for &'a Projects {
|
||||
type IntoIter = std::slice::Iter<'a, Project>;
|
||||
type Item = &'a Project;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.list.iter()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn read_projects_file() -> Result<Projects> {
|
||||
let projects_file = dirs::data_path().join("projects");
|
||||
|
||||
if !projects_file.exists() {
|
||||
return Ok(Projects::default());
|
||||
}
|
||||
|
||||
let file = std::fs::File::open(projects_file)?;
|
||||
let projects = bincode::deserialize_from(file)?;
|
||||
|
||||
Ok(projects)
|
||||
}
|
||||
|
||||
|
||||
pub fn write_projects_file(projects: &Projects) -> Result<()> {
|
||||
let projects_file = dirs::data_path().join("projects");
|
||||
|
||||
let file = fs::OpenOptions::new()
|
||||
.write(true)
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.open(projects_file)?;
|
||||
|
||||
bincode::serialize_into(file, projects)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
pub fn clear_selected_project_file() -> Result<()> {
|
||||
@ -29,31 +95,3 @@ pub fn write_selected_project_file(project: &Project) -> Result<()> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn write_projects_file(projects: &Projects) -> Result<()> {
|
||||
let projects_file = dirs::data_path().join("projects");
|
||||
|
||||
let file = fs::OpenOptions::new()
|
||||
.write(true)
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.open(projects_file)?;
|
||||
|
||||
bincode::serialize_into(file, projects)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
pub fn read_projects_file() -> Result<Projects> {
|
||||
let projects_file = dirs::data_path().join("projects");
|
||||
|
||||
if !projects_file.exists() {
|
||||
return Ok(Projects::default());
|
||||
}
|
||||
|
||||
let file = std::fs::File::open(projects_file)?;
|
||||
let projects = bincode::deserialize_from(file)?;
|
||||
|
||||
Ok(projects)
|
||||
}
|
24
src/projects/v1.rs
Normal file
24
src/projects/v1.rs
Normal file
@ -0,0 +1,24 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||
pub struct Project {
|
||||
path: PathBuf,
|
||||
}
|
||||
|
||||
impl Project {
|
||||
pub fn path(&self) -> &PathBuf {
|
||||
&self.path
|
||||
}
|
||||
|
||||
pub fn name(&self) -> String {
|
||||
let name = self.path.file_name().unwrap();
|
||||
name.to_string_lossy().to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PathBuf> for Project {
|
||||
fn from(path: PathBuf) -> Self {
|
||||
Self { path }
|
||||
}
|
||||
}
|
11
src/tui.rs
11
src/tui.rs
@ -11,8 +11,9 @@ use ratatui::Frame;
|
||||
use tracing::trace;
|
||||
use tui_input::{Input, InputRequest};
|
||||
|
||||
use crate::state::{clear_selected_project_file, write_selected_project_file};
|
||||
use crate::{Project, Projects};
|
||||
use crate::projects::{
|
||||
clear_selected_project_file, write_selected_project_file, Project, Projects,
|
||||
};
|
||||
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
@ -219,14 +220,14 @@ fn draw_status(state: &mut State, frame: &mut Frame, area: Rect) {
|
||||
|
||||
fn draw_list(state: &mut State, frame: &mut Frame, area: Rect) {
|
||||
let search_value = state.search.value();
|
||||
let projects = &state.projects.list;
|
||||
let projects = &state.projects;
|
||||
|
||||
state.filtered_projects = if search_value.is_empty() {
|
||||
projects.clone()
|
||||
projects.list().to_vec()
|
||||
} else {
|
||||
let mut filtered = VecDeque::new();
|
||||
|
||||
for project in projects.iter() {
|
||||
for project in projects {
|
||||
match fuzzy_search(search_value, &project.name()) {
|
||||
Some(indices) => {
|
||||
trace!(?search_value, ?project, ?indices);
|
||||
|
Loading…
Reference in New Issue
Block a user