diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index e2f2b38..0000000 Binary files a/.DS_Store and /dev/null differ diff --git a/.gitignore b/.gitignore index ea8c4bf..bcd5559 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ /target + +.DS_Store diff --git a/README.md b/README.md index 2e82b65..798aacc 100644 --- a/README.md +++ b/README.md @@ -85,6 +85,36 @@ then jump to `demo` with: gg demo ``` +### Show Git Tags + +List git tags in chronological order. By default, it shows the latest 10 tags. + +```bash +in tags +``` + +Example output: +``` +Showing the last 10 of 12 tags (from 2025-07-31 to 2025-07-31). Use --all to see all. + +2025-07-31 v0.1.03 Test tag 3 +2025-07-31 v0.1.04 Test tag 4 +2025-07-31 v0.1.05 Test tag 5 +2025-07-31 v0.1.06 Test tag 6 +2025-07-31 v0.1.07 Test tag 7 +2025-07-31 v0.1.08 Test tag 8 +2025-07-31 v0.1.09 Test tag 9 +2025-07-31 v0.1.10 Test tag 10 +2025-07-31 v0.1.11 Test tag 11 +2025-07-31 v0.1.12 Test tag 12 +``` + +To view all tags, use the `--all` flag. + +```bash +in tags --all +``` + ### License MIT diff --git a/src/args.rs b/src/args.rs index 02c7fda..097087d 100644 --- a/src/args.rs +++ b/src/args.rs @@ -18,6 +18,7 @@ pub enum InspectionCommand { ListFileSize(InspectForFileSize), DirMark(InspectForDirMark), FinishBranch(InspectForFinishBranch), + ShowTags(InspectForTags), } /// command for inspecting IP addresses. @@ -29,6 +30,15 @@ pub struct InspectForIp { pub detailed: bool, } +/// command for showing tags. +#[derive(FromArgs, PartialEq, Debug)] +#[argh(subcommand, name = "tags")] +pub struct InspectForTags { + /// show all tags + #[argh(switch, long = "all")] + pub all: bool, +} + /// command for copying files. #[derive(FromArgs, PartialEq, Debug)] #[argh(subcommand, name = "cpfile")] diff --git a/src/main.rs b/src/main.rs index f93bccc..fbb6a77 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ mod args; mod dir_marks; mod git; mod show_file_size; +mod tags; use sysinfo::System; @@ -123,6 +124,12 @@ fn main() -> Result<(), String> { std::process::exit(1); } } + ShowTags(options) => { + if let Err(e) = tags::show_tags(&options) { + eprintln!("Error showing tags: {}", e); + std::process::exit(1); + } + } } Ok(()) diff --git a/src/tags.rs b/src/tags.rs new file mode 100644 index 0000000..d864cf0 --- /dev/null +++ b/src/tags.rs @@ -0,0 +1,93 @@ +use crate::args::InspectForTags; +use std::process::Command; + +#[derive(Clone)] +struct TagInfo { + date: String, + name: String, + subject: String, +} + +pub fn show_tags(options: &InspectForTags) -> Result<(), String> { + let output = Command::new("git") + .args([ + "for-each-ref", + "--sort=creatordate", // Sort by date ascending + "--format=%(creatordate:short)\t%(refname:short)\t%(subject)", + "refs/tags", + ]) + .output() + .map_err(|e| e.to_string())?; + + if !output.status.success() { + return Err(String::from_utf8_lossy(&output.stderr).to_string()); + } + + let output_str = String::from_utf8_lossy(&output.stdout); + if output_str.is_empty() { + println!("No tags found."); + return Ok(()); + } + + let all_tags: Vec = output_str + .lines() + .filter_map(|line| { + let parts: Vec<&str> = line.splitn(3, '\t').collect(); + if parts.len() == 3 { + Some(TagInfo { + date: parts[0].to_string(), + name: parts[1].to_string(), + subject: parts[2].to_string(), + }) + } else { + None + } + }) + .collect(); + + let total_tags = all_tags.len(); + let tags_to_display = if options.all { + all_tags.clone() + } else { + let tags: Vec = all_tags.iter().rev().take(10).cloned().collect(); + tags.into_iter().rev().collect() + }; + + if tags_to_display.is_empty() { + println!("No tags to display."); + return Ok(()); + } + + if !options.all && total_tags > tags_to_display.len() { + if let (Some(first_tag), Some(last_tag)) = (all_tags.first(), all_tags.last()) { + println!( + "Showing the last {} of {} tags (from {} to {}). Use --all to see all.", + tags_to_display.len(), + total_tags, + first_tag.date, + last_tag.date + ); + println!(); // Add a blank line for separation + } + } + + + let mut max_tag_width = 0; + for tag in &tags_to_display { + if tag.name.len() > max_tag_width { + max_tag_width = tag.name.len(); + } + } + + for tag in tags_to_display { + println!( + "{} {: