9
9
{
10
10
var config = LoadConfig ( ) ;
11
11
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 ) ;
14
41
15
42
var sw = Stopwatch . StartNew ( ) ;
16
43
var content = BuildContent ( path , config ) ;
17
44
var stats = CalculateStats ( path , content , sw . Elapsed ) ;
18
45
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
21
49
Console . WriteLine ( stats ) ;
22
50
}
23
51
catch ( Exception ex )
@@ -35,17 +63,29 @@ static string GetValidPath(string defaultPath)
35
63
{
36
64
var path = MyAppsContext . GetUserInput ( $ "Enter the path to index (default: { defaultPath } ): ") ;
37
65
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 } ") ;
41
71
}
42
72
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 )
44
75
{
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
47
86
}
48
87
88
+
49
89
static string BuildContent ( string path , Config config )
50
90
{
51
91
try
@@ -74,35 +114,56 @@ static string BuildContent(string path, Config config)
74
114
75
115
static string CalculateStats ( string path , string content , TimeSpan timeTaken ) =>
76
116
$ """
77
-
117
+
78
118
📊 Stats:
79
119
📁 Files processed: { Directory . GetFiles ( path , "*" , SearchOption . AllDirectories ) . Length }
80
120
📝 Total lines: { content . Count ( c => c == '\n ' ) }
81
121
⏱️ Time taken: { timeTaken . TotalSeconds : F2} s
82
122
💾 Output size: { content . Length } characters
83
123
""" ;
84
124
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 )
86
127
{
87
128
Console . WriteLine ( "\n 💾 Writing output..." ) ;
129
+ string resolvedFilePath = "" ;
88
130
try
89
131
{
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
+
91
149
var formattedContent = format . ToLower ( ) == "json"
92
150
? JsonSerializer . Serialize ( new { content , timestamp = DateTime . Now } )
93
151
: content ;
94
- File . WriteAllText ( outputPath , formattedContent ) ;
152
+ File . WriteAllText ( resolvedFilePath , formattedContent ) ;
153
+ return resolvedFilePath ; // Return the actual path
95
154
}
96
155
catch ( Exception ex )
97
156
{
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 ) ;
99
160
}
100
161
}
101
162
102
163
record Config
103
164
{
104
165
public string DefaultInputPath { get ; init ; } = "." ;
105
- public string DefaultOutputFileName { get ; init ; } = "context.txt" ;
166
+ public string DefaultOutputFileName { get ; init ; } = "context.txt" ; // Base name
106
167
public string OutputFormat { get ; init ; } = "text" ;
107
168
public bool IncludeStructure { get ; init ; } = true ;
108
169
public bool IncludeContents { get ; init ; } = true ;
0 commit comments