Skip to content

Commit a02d07d

Browse files
author
yashksaini-coder
committed
first run semi-pass
1 parent b6f8438 commit a02d07d

File tree

5 files changed

+133
-19
lines changed

5 files changed

+133
-19
lines changed

src/app.rs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,34 @@
1-
// TODO: TO create a app for the project
1+
use crate::scanner::VenvInfo;
22

3-
pub fn create_app() -> Result<(), Box<dyn Error>> {
3+
pub struct App {
4+
pub venvs: Vec<VenvInfo>,
5+
pub selected: usize, // index of selected venv
6+
}
7+
8+
impl App {
9+
pub fn new(venvs: Vec<VenvInfo>) -> Self {
10+
Self {
11+
venvs,
12+
selected: 0,
13+
}
14+
}
15+
16+
/// Move selection up
17+
pub fn previous(&mut self) {
18+
if self.selected > 0 {
19+
self.selected -= 1;
20+
}
21+
}
422

5-
let app = App::new();
23+
/// Move selection down
24+
pub fn next(&mut self) {
25+
if self.selected + 1 < self.venvs.len() {
26+
self.selected += 1;
27+
}
28+
}
629

30+
/// Get the currently selected venv, if any
31+
pub fn selected_venv(&self) -> Option<&VenvInfo> {
32+
self.venvs.get(self.selected)
33+
}
734
}

src/main.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,25 @@
1+
mod scanner;
2+
mod utils;
3+
mod app;
4+
mod ui;
5+
6+
use std::env;
7+
use app::App;
8+
use scanner::scan_for_venvs;
9+
use ui::draw_ui;
10+
111
fn main() {
2-
println!("Hello, world!");
3-
12+
let cwd = env::current_dir().unwrap();
13+
let venvs = scan_for_venvs(&cwd);
14+
15+
let mut app = App::new(venvs);
16+
17+
// Simulate some navigation
18+
draw_ui(&app);
19+
println!("\n-- Moving down --");
20+
app.next();
21+
draw_ui(&app);
22+
println!("\n-- Moving up --");
23+
app.previous();
24+
draw_ui(&app);
425
}

src/scanner.rs

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,68 @@
1-
// TODO: TO create a scanner that will scan the project for virtual environment of python using sys.prefix
1+
use std::fs;
2+
use std::path::{Path, PathBuf};
3+
use chrono::{DateTime, Local};
4+
use walkdir::WalkDir;
25

3-
pub fn scan_project(project_path: &str) -> Result<(), Box<dyn Error>> {
6+
#[derive(Debug)]
7+
pub struct VenvInfo {
8+
pub path: PathBuf,
9+
pub size: u64,
10+
pub last_modified: Option<DateTime<Local>>,
11+
}
12+
13+
impl VenvInfo {
14+
pub fn new(path: PathBuf) -> Option<Self> {
15+
// Check if this is really a virtualenv
16+
let pyvenv_cfg = path.join("pyvenv.cfg");
17+
if !pyvenv_cfg.exists() {
18+
return None;
19+
}
20+
21+
// Calculate size
22+
let size = get_dir_size(&path).unwrap_or(0);
23+
24+
// Get last modified time
25+
let metadata = fs::metadata(&path).ok()?;
26+
let modified = metadata.modified().ok()
27+
.and_then(|t| DateTime::<Local>::from(t).into());
28+
29+
Some(Self {
30+
path,
31+
size,
32+
last_modified: modified,
33+
})
34+
}
35+
}
36+
37+
/// Scan a directory recursively for potential Python virtualenv folders
38+
pub fn scan_for_venvs(root: &Path) -> Vec<VenvInfo> {
39+
let mut results = Vec::new();
40+
41+
for entry in WalkDir::new(root).into_iter().filter_map(Result::ok) {
42+
if !entry.file_type().is_dir() {
43+
continue;
44+
}
445

5-
let project_path = Path::new(project_path);
6-
let project_path = project_path.canonicalize()?;
46+
let name = entry.file_name().to_string_lossy().to_lowercase();
47+
if name == "venv" || name == ".venv" || name == "env" {
48+
if let Some(venv) = VenvInfo::new(entry.path().to_path_buf()) {
49+
results.push(venv);
50+
}
51+
}
52+
}
53+
54+
results
55+
}
756

8-
let project_path = project_path.to_str().unwrap();
57+
/// Recursively calculate directory size in bytes
58+
fn get_dir_size(path: &Path) -> Result<u64, std::io::Error> {
59+
let mut size = 0;
960

10-
let project_path = project_path.to_string();
61+
for entry in WalkDir::new(path).into_iter().filter_map(Result::ok) {
62+
if entry.file_type().is_file() {
63+
size += entry.metadata()?.len();
64+
}
65+
}
1166

67+
Ok(size)
1268
}

src/ui.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
1-
// TODO: TO create a ui for the project
1+
use crate::app::App;
22

3-
pub fn create_ui() -> Result<(), Box<dyn Error>> {
3+
pub fn draw_ui(app: &App) {
4+
println!("Found {} virtual environments:\n", app.venvs.len());
45

5-
let ui = Ui::new();
6+
for (i, venv) in app.venvs.iter().enumerate() {
7+
let marker = if i == app.selected { ">" } else { " " };
8+
let size_mb = venv.size / 1024 / 1024;
69

10+
println!(
11+
"{} [{} MB] {}",
12+
marker,
13+
size_mb,
14+
venv.path.display()
15+
);
16+
}
717
}

src/utils.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
// TODO: TO create a utils for the project
1+
use std::fs;
2+
use std::path::Path;
23

3-
pub fn get_project_path() -> Result<(), Box<dyn Error>> {
4-
5-
let project_path = Path::new(project_path);
6-
let project_path = project_path.canonicalize()?;
4+
/// Deletes a directory recursively
5+
pub fn delete_venv(path: &Path) -> Result<(), std::io::Error> {
6+
fs::remove_dir_all(path)
77
}

0 commit comments

Comments
 (0)