99{
1010 var config = LoadConfig ( ) ;
1111 var path = GetValidPath ( args . FirstOrDefault ( ) ?? config . DefaultInputPath ) ;
12- var defaultOutput = Path . Combine ( Path . GetDirectoryName ( path ) ?? "." , config . DefaultOutputFileName ) ;
13- var output = GetValidOutputPath ( args . ElementAtOrDefault ( 1 ) ?? defaultOutput ) ;
12+
13+ // 1. Get input folder name
14+ var inputFolderName = new DirectoryInfo ( path ) . Name ;
15+ if ( string . IsNullOrEmpty ( inputFolderName ) || inputFolderName == "." ) // Handle cases like "." or "C:\"
16+ {
17+ // For "." use current directory name, for root drives, use a generic name or drive letter
18+ inputFolderName = new DirectoryInfo ( Environment . CurrentDirectory ) . Name ;
19+ if ( path . EndsWith ( Path . DirectorySeparatorChar . ToString ( ) ) || path . EndsWith ( Path . AltDirectorySeparatorChar . ToString ( ) ) )
20+ {
21+ // If path was like "C:/", DirectoryInfo(path).Name might be "C:".
22+ // Let's try to get a more descriptive name if it's a root drive.
23+ var root = Path . GetPathRoot ( Path . GetFullPath ( path ) ) ;
24+ if ( ! string . IsNullOrEmpty ( root ) )
25+ {
26+ inputFolderName = root . Replace ( Path . DirectorySeparatorChar . ToString ( ) , "" ) . Replace ( Path . AltDirectorySeparatorChar . ToString ( ) , "" ) . Replace ( ":" , "" ) ;
27+ if ( string . IsNullOrEmpty ( inputFolderName ) ) inputFolderName = "root" ;
28+ }
29+ }
30+ }
31+
32+
33+ // 2. Construct prefixed default file name
34+ var prefixedDefaultFileName = $ "{ inputFolderName } _{ config . DefaultOutputFileName } ";
35+
36+ // 3. Default output is INSIDE the input path folder with the prefixed name
37+ var defaultFullOutputPath = Path . Combine ( path , prefixedDefaultFileName ) ;
38+
39+ // 4. Get final output path (could be a file or directory specified by user, or the default)
40+ var outputTarget = GetValidOutputPath ( args . ElementAtOrDefault ( 1 ) , defaultFullOutputPath ) ;
1441
1542 var sw = Stopwatch . StartNew ( ) ;
1643 var content = BuildContent ( path , config ) ;
1744 var stats = CalculateStats ( path , content , sw . Elapsed ) ;
1845
19- WriteOutput ( output , content , config . OutputFormat ) ;
20- Console . WriteLine ( $ "\n ✅ Output written to { output } ") ;
46+ // 5. Pass prefixedDefaultFileName to WriteOutput
47+ string actualOutputPath = WriteOutput ( outputTarget , content , config . OutputFormat , prefixedDefaultFileName ) ;
48+ Console . WriteLine ( $ "\n ✅ Output written to { actualOutputPath } ") ; // 6. Use actual output path
2149 Console . WriteLine ( stats ) ;
2250}
2351catch ( Exception ex )
@@ -35,17 +63,29 @@ static string GetValidPath(string defaultPath)
3563{
3664 var path = MyAppsContext . GetUserInput ( $ "Enter the path to index (default: { defaultPath } ): ") ;
3765 var finalPath = string . IsNullOrWhiteSpace ( path ) ? defaultPath : path ;
38- return Directory . Exists ( finalPath )
39- ? finalPath
40- : throw new DirectoryNotFoundException ( $ "Invalid directory path: { finalPath } ") ;
66+ var fullPath = Path . GetFullPath ( finalPath ) ; // Resolve to full path for consistency
67+
68+ return Directory . Exists ( fullPath )
69+ ? fullPath
70+ : throw new DirectoryNotFoundException ( $ "Invalid directory path: { fullPath } ") ;
4171}
4272
43- static string GetValidOutputPath ( string defaultOutput )
73+ // Modified to accept user's argument and the fully resolved default path
74+ static string GetValidOutputPath ( string ? outputArgFromUser , string defaultFullOutputPathIfNoArgAndNoInput )
4475{
45- var output = MyAppsContext . GetUserInput ( $ "Enter output file (default: { defaultOutput } ): ") ;
46- return string . IsNullOrWhiteSpace ( output ) ? defaultOutput : output ;
76+ // If an argument is provided, use it directly.
77+ if ( ! string . IsNullOrWhiteSpace ( outputArgFromUser ) )
78+ {
79+ return Path . GetFullPath ( outputArgFromUser ) ; // Resolve to full path
80+ }
81+ // Otherwise, prompt the user, showing the calculated default.
82+ var userInput = MyAppsContext . GetUserInput ( $ "Enter output file/directory (default: { defaultFullOutputPathIfNoArgAndNoInput } ): ") ;
83+ return string . IsNullOrWhiteSpace ( userInput )
84+ ? defaultFullOutputPathIfNoArgAndNoInput
85+ : Path . GetFullPath ( userInput ) ; // Resolve to full path
4786}
4887
88+
4989static string BuildContent ( string path , Config config )
5090{
5191 try
@@ -74,35 +114,56 @@ static string BuildContent(string path, Config config)
74114
75115static string CalculateStats ( string path , string content , TimeSpan timeTaken ) =>
76116 $ """
77-
117+
78118 📊 Stats:
79119 📁 Files processed: { Directory . GetFiles ( path , "*" , SearchOption . AllDirectories ) . Length }
80120 📝 Total lines: { content . Count ( c => c == '\n ' ) }
81121 ⏱️ Time taken: { timeTaken . TotalSeconds : F2} s
82122 💾 Output size: { content . Length } characters
83123 """ ;
84124
85- static void WriteOutput ( string output , string content , string format )
125+ // Modified to accept the effective output filename and return the actual path written
126+ static string WriteOutput ( string outputTarget , string content , string format , string effectiveOutputFileName )
86127{
87128 Console . WriteLine ( "\n 💾 Writing output..." ) ;
129+ string resolvedFilePath = "" ;
88130 try
89131 {
90- var outputPath = Directory . Exists ( output ) ? Path . Combine ( output , "context.txt" ) : output ;
132+ // If outputTarget is an existing directory, combine it with the effectiveOutputFileName.
133+ // Otherwise, assume outputTarget is the full file path.
134+ if ( Directory . Exists ( outputTarget ) )
135+ {
136+ resolvedFilePath = Path . Combine ( outputTarget , effectiveOutputFileName ) ;
137+ }
138+ else
139+ {
140+ resolvedFilePath = outputTarget ;
141+ // Ensure the directory for the output file exists
142+ var outputDirectory = Path . GetDirectoryName ( resolvedFilePath ) ;
143+ if ( ! string . IsNullOrEmpty ( outputDirectory ) && ! Directory . Exists ( outputDirectory ) )
144+ {
145+ Directory . CreateDirectory ( outputDirectory ) ;
146+ }
147+ }
148+
91149 var formattedContent = format . ToLower ( ) == "json"
92150 ? JsonSerializer . Serialize ( new { content , timestamp = DateTime . Now } )
93151 : content ;
94- File . WriteAllText ( outputPath , formattedContent ) ;
152+ File . WriteAllText ( resolvedFilePath , formattedContent ) ;
153+ return resolvedFilePath ; // Return the actual path
95154 }
96155 catch ( Exception ex )
97156 {
98- throw new IOException ( $ "Error writing output to { output } ", ex ) ;
157+ // Try to provide a more specific path in the error if resolvedFilePath was determined
158+ string errorPath = string . IsNullOrEmpty ( resolvedFilePath ) ? outputTarget : resolvedFilePath ;
159+ throw new IOException ( $ "Error writing output to { errorPath } ", ex ) ;
99160 }
100161}
101162
102163record Config
103164{
104165 public string DefaultInputPath { get ; init ; } = "." ;
105- public string DefaultOutputFileName { get ; init ; } = "context.txt" ;
166+ public string DefaultOutputFileName { get ; init ; } = "context.txt" ; // Base name
106167 public string OutputFormat { get ; init ; } = "text" ;
107168 public bool IncludeStructure { get ; init ; } = true ;
108169 public bool IncludeContents { get ; init ; } = true ;
0 commit comments