Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,15 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and

_Nothing yet._

[Unreleased]: https://github.com/noahbclarkson/codebase_viewer/compare/v0.1.1...HEAD
[Unreleased]: https://github.com/noahbclarkson/codebase_viewer/compare/v0.1.2...HEAD

---

## [0.1.2] - 2025-06-04

### Added
- Copy generated reports directly to the clipboard via a new button.
- `arboard` dependency for cross-platform clipboard access.

---

Expand All @@ -36,6 +44,7 @@ _Nothing yet._
- Explicit revision pin for **cross** install.

[0.1.1]: https://github.com/noahbclarkson/codebase_viewer/releases/tag/v0.1.1
[0.1.2]: https://github.com/noahbclarkson/codebase_viewer/releases/tag/v0.1.2

---

Expand Down
3 changes: 2 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "codebase_viewer"
version = "0.1.1"
version = "0.1.2"
edition = "2021"
authors = ["Noah Clarkson <mrnoahclarkson@gmail.com>"]
description = "A cross-platform desktop tool written in Rust to scan, explore, and document codebases using egui."
Expand Down Expand Up @@ -38,6 +38,7 @@ image = { version = "0.25", default-features = false, features = ["png", "jpeg",
regex = "1.11"
egui-phosphor = "0.9"
egui_material_icons = "0.3.0"
arboard = "3.5"

[profile.release]
codegen-units = 1
Expand Down
54 changes: 54 additions & 0 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use crate::{
task::{ScanMessage, TaskMessage}, // Use items from task module
ui, // Use the ui module's drawing functions
};
use arboard::Clipboard;
use crossbeam_channel::{Receiver, Sender};
use egui::{style::Visuals, CentralPanel, Context, Key, Modifiers, SidePanel};
use rfd::MessageDialogResult;
Expand Down Expand Up @@ -146,6 +147,8 @@ pub(crate) enum AppAction {
LoadSelection,
/// Generate a report with the specified options.
GenerateReport(ReportOptions),
/// Generate a report and copy the output to the clipboard.
CopyReport(ReportOptions),
/// Start scanning a new directory path.
StartScan(PathBuf),
/// Request cancellation of the currently running scan.
Expand Down Expand Up @@ -245,6 +248,7 @@ impl CodebaseApp {
AppAction::SaveSelection => self.perform_save_selection(),
AppAction::LoadSelection => self.perform_load_selection(),
AppAction::GenerateReport(opts) => self.perform_generate_report(opts),
AppAction::CopyReport(opts) => self.perform_copy_report(opts),
AppAction::StartScan(path) => self.perform_start_scan(path),
AppAction::CancelScan => self.perform_cancel_scan(),
AppAction::FocusSearchBox => self.perform_focus_search_box(),
Expand Down Expand Up @@ -647,6 +651,56 @@ impl CodebaseApp {
}
}

/// Generates a report and copies the content to the clipboard.
fn perform_copy_report(&mut self, options: ReportOptions) {
if self.is_scanning || self.is_generating_report {
log::warn!("Cannot copy report: Another background task is running.");
self.status_message = "Busy with another task (scan/report).".to_string();
return;
}
if self.root_path.is_none() || self.root_id.is_none() {
self.status_message = "No directory open to generate report from.".to_string();
log::warn!("Copy report attempted with no directory open.");
return;
}

match report::generate_report(self, &options) {
Ok(content) => match Clipboard::new() {
Ok(mut clipboard) => {
if let Err(e) = clipboard.set_text(content) {
log::error!("Failed to copy report to clipboard: {}", e);
self.status_message = format!("Error copying report: {}", e);
rfd::MessageDialog::new()
.set_level(rfd::MessageLevel::Error)
.set_title("Copy Report Failed")
.set_description(format!("Could not copy report:\n{}", e))
.show();
} else {
self.status_message = "Report copied to clipboard.".to_string();
}
}
Err(e) => {
log::error!("Failed to access clipboard: {}", e);
self.status_message = format!("Clipboard error: {}", e);
rfd::MessageDialog::new()
.set_level(rfd::MessageLevel::Error)
.set_title("Clipboard Error")
.set_description(format!("Could not access clipboard:\n{}", e))
.show();
}
},
Err(e) => {
log::error!("Failed to generate report for clipboard: {}", e);
self.status_message = format!("Error generating report: {}", e);
rfd::MessageDialog::new()
.set_level(rfd::MessageLevel::Error)
.set_title("Report Generation Failed")
.set_description(format!("Could not generate report:\n{}", e))
.show();
}
}
}

/// Sets the focus flag for the search box.
fn perform_focus_search_box(&mut self) {
self.focus_search_box = true;
Expand Down
20 changes: 20 additions & 0 deletions src/ui/dialogs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ pub fn draw_report_options_window(app: &mut CodebaseApp, ctx: &Context) {
}

let mut generate_clicked = false;
let mut copy_clicked = false;
let mut cancel_clicked = false;
let mut is_open = true;

Expand Down Expand Up @@ -266,6 +267,16 @@ pub fn draw_report_options_window(app: &mut CodebaseApp, ctx: &Context) {
{
generate_clicked = true;
}
if ui
.add_enabled(
!app.is_scanning && !app.is_generating_report,
Button::new("Copy to Clipboard"),
)
.on_hover_text("Copy the report to the clipboard")
.clicked()
{
copy_clicked = true;
}
if app.is_scanning || app.is_generating_report {
ui.label(RichText::new("Busy...").color(Color32::RED).small());
}
Expand All @@ -290,6 +301,15 @@ pub fn draw_report_options_window(app: &mut CodebaseApp, ctx: &Context) {
app.show_report_options_window = false; // Close the dialog
}
}

// Handle Copy button click
if copy_clicked {
if let Some(opts) = app.report_options_draft.take() {
app.last_report_options = opts.clone();
app.queue_action(AppAction::CopyReport(opts));
app.show_report_options_window = false;
}
}
}

/// Draws the About window (modal).
Expand Down