11use colored:: * ;
2- use log:: { debug, info} ;
2+ use log:: { debug, info, warn } ;
33use rb_core:: bundler:: BundlerRuntime ;
44use rb_core:: butler:: ButlerRuntime ;
5+ use rb_core:: project:: { ProjectRuntime , RbprojectDetector } ;
56use rb_core:: ruby:: RubyType ;
7+ use std:: path:: PathBuf ;
68
7- pub fn environment_command ( butler_runtime : & ButlerRuntime ) {
9+ pub fn environment_command ( butler_runtime : & ButlerRuntime , project_file : Option < PathBuf > ) {
810 info ! ( "Presenting current Ruby environment from the working directory" ) ;
9- present_current_environment ( butler_runtime) ;
11+ present_current_environment ( butler_runtime, project_file ) ;
1012}
1113
12- fn present_current_environment ( butler_runtime : & ButlerRuntime ) {
14+ fn present_current_environment ( butler_runtime : & ButlerRuntime , project_file : Option < PathBuf > ) {
1315 println ! ( "{}" , "🌍 Your Current Ruby Environment" . to_string( ) . bold( ) ) ;
1416 println ! ( ) ;
1517
@@ -26,14 +28,59 @@ fn present_current_environment(butler_runtime: &ButlerRuntime) {
2628 // Get gem runtime from butler runtime
2729 let gem_runtime = butler_runtime. gem_runtime ( ) ;
2830
31+ // Detect or load project runtime
32+ let project_runtime = if let Some ( path) = project_file {
33+ // Use specified project file
34+ debug ! (
35+ "Loading rbproject.toml from specified path: {}" ,
36+ path. display( )
37+ ) ;
38+ match ProjectRuntime :: from_file ( & path) {
39+ Ok ( project) => {
40+ debug ! (
41+ "Loaded rbproject.toml with {} scripts" ,
42+ project. scripts. len( )
43+ ) ;
44+ Some ( project)
45+ }
46+ Err ( e) => {
47+ warn ! (
48+ "Failed to load specified rbproject.toml at {}: {}" ,
49+ path. display( ) ,
50+ e
51+ ) ;
52+ None
53+ }
54+ }
55+ } else {
56+ // Auto-detect project file
57+ RbprojectDetector :: discover ( current_dir)
58+ . ok ( )
59+ . flatten ( )
60+ . map ( |project| {
61+ debug ! (
62+ "Discovered rbproject.toml with {} scripts" ,
63+ project. scripts. len( )
64+ ) ;
65+ project
66+ } )
67+ } ;
68+
2969 // Present the environment
30- present_environment_details ( ruby, gem_runtime, bundler_runtime, butler_runtime) ;
70+ present_environment_details (
71+ ruby,
72+ gem_runtime,
73+ bundler_runtime,
74+ project_runtime. as_ref ( ) ,
75+ butler_runtime,
76+ ) ;
3177}
3278
3379fn present_environment_details (
3480 ruby : & rb_core:: ruby:: RubyRuntime ,
3581 gem_runtime : Option < & rb_core:: gems:: GemRuntime > ,
3682 bundler_runtime : Option < & BundlerRuntime > ,
83+ project_runtime : Option < & ProjectRuntime > ,
3784 butler : & ButlerRuntime ,
3885) {
3986 let label_width = [
@@ -189,6 +236,79 @@ fn present_environment_details(
189236 println ! ( " {}" , "Bundler environment not detected" . bright_black( ) ) ;
190237 }
191238
239+ // Present Project Environment (if detected)
240+ if let Some ( project) = project_runtime {
241+ println ! ( ) ;
242+ println ! ( "{}" , "📋 Project" . green( ) . bold( ) ) ;
243+
244+ // Display project name if available
245+ if let Some ( name) = & project. metadata . name {
246+ println ! (
247+ " {:<width$}: {}" ,
248+ "Name" . bright_blue( ) . bold( ) ,
249+ name. bright_black( ) ,
250+ width = label_width
251+ ) ;
252+ }
253+
254+ // Display project description if available
255+ if let Some ( description) = & project. metadata . description {
256+ println ! (
257+ " {:<width$}: {}" ,
258+ "Description" . bright_blue( ) . bold( ) ,
259+ description. bright_black( ) ,
260+ width = label_width
261+ ) ;
262+ }
263+
264+ println ! (
265+ " {:<width$}: {}" ,
266+ "Project file" . bright_blue( ) . bold( ) ,
267+ project
268+ . rbproject_path( )
269+ . display( )
270+ . to_string( )
271+ . bright_black( ) ,
272+ width = label_width
273+ ) ;
274+
275+ println ! (
276+ " {:<width$}: {}" ,
277+ "Scripts loaded" . bright_blue( ) . bold( ) ,
278+ format!( "{}" , project. scripts. len( ) ) . bright_black( ) ,
279+ width = label_width
280+ ) ;
281+
282+ if !project. scripts . is_empty ( ) {
283+ println ! ( ) ;
284+ println ! ( " {}" , "Available Scripts:" . bright_blue( ) . bold( ) ) ;
285+
286+ // Get sorted script names for consistent display
287+ let script_names = project. script_names ( ) ;
288+ for name in script_names {
289+ let script = project. get_script ( name) . unwrap ( ) ;
290+ let command = script. command ( ) ;
291+
292+ // Always show: name → command
293+ println ! (
294+ " {} {} {}" ,
295+ name. cyan( ) . bold( ) ,
296+ "→" . bright_black( ) ,
297+ command. to_string( ) . bright_black( )
298+ ) ;
299+
300+ // Optionally show description on next line with more indent
301+ if let Some ( description) = script. description ( ) {
302+ println ! ( " {}" , description. bright_black( ) . italic( ) ) ;
303+ }
304+ }
305+ }
306+ } else {
307+ println ! ( ) ;
308+ println ! ( "{}" , "📋 Project Scripts" . bright_black( ) ) ;
309+ println ! ( " {}" , "No rbproject.toml detected" . bright_black( ) ) ;
310+ }
311+
192312 // Present environment summary
193313 println ! ( ) ;
194314 println ! ( "{}" , "🎯 Environment Summary" . green( ) . bold( ) ) ;
@@ -262,7 +382,7 @@ mod tests {
262382 . expect ( "Failed to create butler runtime with test Ruby" ) ;
263383
264384 // This will handle the environment presentation gracefully
265- environment_command ( & butler_runtime) ;
385+ environment_command ( & butler_runtime, None ) ;
266386 }
267387
268388 #[ test]
@@ -283,7 +403,7 @@ mod tests {
283403 let butler = ButlerRuntime :: new ( ruby. clone ( ) , Some ( gem_runtime. clone ( ) ) ) ;
284404
285405 // Test with no bundler environment
286- present_environment_details ( & ruby, Some ( & gem_runtime) , None , & butler) ;
406+ present_environment_details ( & ruby, Some ( & gem_runtime) , None , None , & butler) ;
287407
288408 Ok ( ( ) )
289409 }
@@ -310,7 +430,61 @@ mod tests {
310430 let butler = ButlerRuntime :: new ( ruby. clone ( ) , Some ( gem_runtime. clone ( ) ) ) ;
311431
312432 // Test with bundler environment
313- present_environment_details ( & ruby, Some ( & gem_runtime) , Some ( & bundler_runtime) , & butler) ;
433+ present_environment_details (
434+ & ruby,
435+ Some ( & gem_runtime) ,
436+ Some ( & bundler_runtime) ,
437+ None ,
438+ & butler,
439+ ) ;
440+
441+ Ok ( ( ) )
442+ }
443+
444+ #[ test]
445+ fn present_environment_details_with_project ( ) -> std:: io:: Result < ( ) > {
446+ use rb_core:: gems:: GemRuntime ;
447+ use rb_core:: project:: { ProjectMetadata , ScriptDefinition } ;
448+ use rb_tests:: RubySandbox ;
449+ use std:: collections:: HashMap ;
450+
451+ let ruby_sandbox = RubySandbox :: new ( ) ?;
452+ let ruby_dir = ruby_sandbox. add_ruby_dir ( "3.2.5" ) ?;
453+ let ruby = rb_core:: ruby:: RubyRuntime :: new (
454+ rb_core:: ruby:: RubyType :: CRuby ,
455+ semver:: Version :: parse ( "3.2.5" ) . unwrap ( ) ,
456+ & ruby_dir,
457+ ) ;
458+
459+ // Create a project runtime with some scripts
460+ let mut scripts = HashMap :: new ( ) ;
461+ scripts. insert (
462+ "test" . to_string ( ) ,
463+ ScriptDefinition :: Detailed {
464+ command : "rspec" . to_string ( ) ,
465+ description : Some ( "Run the test suite" . to_string ( ) ) ,
466+ } ,
467+ ) ;
468+ scripts. insert (
469+ "lint:fix" . to_string ( ) ,
470+ ScriptDefinition :: Simple ( "rubocop -a" . to_string ( ) ) ,
471+ ) ;
472+
473+ let metadata = ProjectMetadata :: default ( ) ;
474+ let project_runtime = ProjectRuntime :: new ( ruby_sandbox. root ( ) , metadata, scripts) ;
475+
476+ // Use sandboxed gem directory
477+ let gem_runtime = GemRuntime :: for_base_dir ( & ruby_sandbox. gem_base_dir ( ) , & ruby. version ) ;
478+ let butler = ButlerRuntime :: new ( ruby. clone ( ) , Some ( gem_runtime. clone ( ) ) ) ;
479+
480+ // Test with project environment
481+ present_environment_details (
482+ & ruby,
483+ Some ( & gem_runtime) ,
484+ None ,
485+ Some ( & project_runtime) ,
486+ & butler,
487+ ) ;
314488
315489 Ok ( ( ) )
316490 }
0 commit comments