worm_hole 2.0.0

CLI tool to easily jump between directories
// Copyright (C) 2025 Rignchen
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

use std::cmp::max;
use std::fmt::Display;

pub struct Alias {
	alias: String,
	path: String,
}

impl From<(String, String)> for Alias {
	fn from((alias, path): (String, String)) -> Self {
		Alias { alias, path }
	}
}

#[allow(clippy::len_without_is_empty)]
impl Alias {
	pub fn len(&self) -> usize {
		self.alias.len()
	}
}

pub struct AliasList {
	aliases: Vec<Alias>,
	alias_max_len: usize,
}

impl Default for AliasList {
	fn default() -> Self {
		Self::new()
	}
}

impl AliasList {
	pub fn new() -> Self {
		AliasList {
			aliases: Vec::new(),
			alias_max_len: 0,
		}
	}

	pub fn add(&mut self, alias: Alias) {
		self.alias_max_len = max(self.alias_max_len, alias.len());
		self.aliases.push(alias);
	}
}

impl Display for AliasList {
	fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
		for alias in &self.aliases {
			writeln!(f, "{:width$} -> {}", alias.alias, alias.path, width = self.alias_max_len)?;
		}
		Ok(())
	}
}

#[cfg(test)]
mod test {
	use super::*;

	#[test]
	fn create_alias() {
		let alias = Alias::from(("alias".to_string(), "path".to_string()));
		assert_eq!(alias.alias, "alias");
		assert_eq!(alias.path, "path");
	}

	#[test]
	fn alias_len() {
		let alias = Alias::from(("alias".to_string(), "path".to_string()));
		assert_eq!(alias.len(), 5);
	}

	#[test]
	fn create_alias_list() {
		let alias_list = AliasList::new();
		assert_eq!(alias_list.aliases.len(), 0);
		assert_eq!(alias_list.alias_max_len, 0);
	}

	#[test]
	fn add_alias() {
		let mut alias_list = AliasList::new();
		alias_list.add(Alias::from(("alias".to_string(), "path".to_string())));
		assert_eq!(alias_list.aliases.len(), 1);
		assert_eq!(alias_list.alias_max_len, 5);
		alias_list.add(Alias::from(("aliases".to_string(), "path".to_string())));
		assert_eq!(alias_list.aliases.len(), 2);
		assert_eq!(alias_list.alias_max_len, 7);
		alias_list.add(Alias::from(("alias2".to_string(), "path".to_string())));
		assert_eq!(alias_list.aliases.len(), 3);
		assert_eq!(alias_list.alias_max_len, 7);
	}

	#[test]
	fn display_alias_list() {
		let mut alias_list = AliasList::new();
		alias_list.add(Alias::from(("alias".to_string(), "path".to_string())));
		alias_list.add(Alias::from(("aliases".to_string(), "path".to_string())));
		alias_list.add(Alias::from(("alias2".to_string(), "path".to_string())));
		assert_eq!(format!("{}", alias_list), "alias   -> path\naliases -> path\nalias2  -> path\n");
	}
}