diff --git a/Cargo.toml b/Cargo.toml index 9ffbe91..9178994 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,3 +5,4 @@ edition = "2021" [dependencies] clap = { version = "4.5.0", features = ["derive"] } +sysinfo = "0.32.0" diff --git a/src/args.rs b/src/arguments.rs similarity index 57% rename from src/args.rs rename to src/arguments.rs index 717fd0a..58587fe 100644 --- a/src/args.rs +++ b/src/arguments.rs @@ -1,23 +1,21 @@ -use clap:: {Parser, Args, Subcommand}; +use clap::{Parser, Args, Subcommand}; + /// implements stack for cd wrapper script -#[derive(Debug, Parser)] -#[clap(author, version, about)] -pub struct CommandArgs -{ - +#[derive(Parser, Debug)] +#[clap(author, version, about, long_about=None)] +pub struct Arguments { /// subcommand - #[clap(subcommand)] - action: Action, + #[command(subcommand)] + pub action: Action, /// process id of parent shell - #[arg(long="pid")] - pid: u32, + #[arg(short, long)] + pub pid: u32, } #[derive(Debug, Clone, Subcommand)] -pub enum Action -{ +pub enum Action { /// navigate to path and add current path to the stack push(PushArgs), @@ -27,13 +25,14 @@ pub enum Action /// display stack stack(StackArgs), - // bookmark(BookmarkArgs), + /// navigate to bookmark and add current path to the stack + bookmark(BookmarkArgs), } #[derive(Debug, Clone, Args)] -pub struct PushArgs -{ +pub struct PushArgs { /// show stack + #[arg(short, long)] show_stack: Option, /// change to @@ -41,21 +40,26 @@ pub struct PushArgs } #[derive(Debug, Clone, Args)] -pub struct PopArgs -{ +pub struct PopArgs { /// show stack #[arg(short, long)] show_stack: Option, } #[derive(Debug, Clone, Args)] -pub struct StackArgs -{ +pub struct StackArgs { /// hide entry numbers - #[arg(short, long)] + #[arg(short='n', long)] hide_numbers: Option, /// show n entries #[arg(short, long="lines")] lines: Option, +} + +#[derive(Debug, Clone, Args)] +pub struct BookmarkArgs { + /// show stack + #[arg(short, long)] + show_stack: Option, } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index c9774ec..9505c8e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,13 @@ -mod args; +mod arguments; +mod stack; -use std::env; use clap::Parser; -use args::CommandArgs; +use arguments::Arguments; +use stack::Stack; -fn main() -{ - let args = CommandArgs::parse(); -} +fn main() { + let args = Arguments::parse(); + + let stack = Stack::new(args.pid); +} \ No newline at end of file diff --git a/src/stack.rs b/src/stack.rs new file mode 100644 index 0000000..13c4f98 --- /dev/null +++ b/src/stack.rs @@ -0,0 +1,99 @@ + +use std::io::{Result}; +use std::fs; +use std::fs::File; +use std::path::{PathBuf}; +use std::str::FromStr; +use sysinfo::{System, Pid}; + + +#[derive(Debug, Clone)] +pub struct Stack +{ + pid: u32, + stack: Vec, +} + +impl Stack +{ + + pub fn new(process_id: u32) -> Result { + let mut stack: Stack = Stack{ + pid : process_id, + stack : Vec::::new(), + }; + + stack.stack = stack.build_stack()?; + + return Ok(stack); + } + + /** + * push entry to stack + * returns updated stack + */ + pub fn push_entry(&mut self, path: PathBuf) -> Vec { + self.stack.push(path); + return self.stack.clone(); + } + + /** + * pop entry from stack + * return poppe entry + */ + pub fn pop_entry(&mut self) -> PathBuf { + return self.stack.pop().unwrap(); + } + + /** + * clean up dead stack files, parse and build stack + */ + fn build_stack(&mut self) -> Result< Vec > { + let stack_dir: PathBuf = PathBuf::from_str("/tmp/navigation/").expect("failed to create path object of '/tmp/navigation'"); + let mut sys = System::new_all(); + sys.refresh_all(); + let procs = sys.processes(); + + if stack_dir.is_dir() { + // clean up stack files of expired processes + let members = fs::read_dir(stack_dir.clone())?; + for entry in members { + let entry = entry?; + let process_id = Pid::from_str(entry.file_name().to_str().expect("failed to convert file name to str")); + if !procs.contains_key(&process_id.expect("failed to convert filename to pid")) { + fs::remove_file(entry.path()).expect("failed to remove orphaned file"); + } + } + } else { + // create temporary directory to store the stack + let _ = fs::create_dir(stack_dir.clone())?; + } + + let mut stack_file_path = stack_dir.clone(); + stack_file_path.push(PathBuf::from(&self.pid.to_string())); + if stack_file_path.is_file() { + // read and parse stack file + let _ = self.parse_stack_file(stack_file_path); + } else { + // create stack file and store current path + let _ = File::create(stack_file_path.clone())?; + } + + return Ok(vec![stack_dir]); + } + + /** + * parse stack file + */ + fn parse_stack_file(&mut self, stack_file_path: PathBuf) -> Result<()> { + let stack = fs::read_to_string(stack_file_path)?; + let stack = stack.split("\n"); + for entry in stack { + self.stack.push(PathBuf::from(entry)); + } + + return Ok(()); + } + +} // end `impl database` +