@@ -3,11 +3,13 @@ use anyhow::Result;
33use bstr:: ByteSlice ;
44use std:: ffi:: OsStr ;
55
6- /// Launches the user's preferred text editor to edit some initial text,
7- /// identified by a unique identifier (to avoid temp file collisions).
8- /// Returns the edited text, with comment lines (starting with '#') removed.
9- pub fn from_editor_no_comments ( identifier : & str , initial_text : & str ) -> Result < String > {
10- let content = from_editor ( identifier, initial_text) ?;
6+ /// Launches the user's preferred text editor to edit some `initial_text`,
7+ /// identified by a `filename_safe_intent` to help the user understand what's wanted of them.
8+ /// Note that this string must be valid in filenames.
9+ ///
10+ /// Returns the edited text, with comment lines (starting with `#`) removed.
11+ pub fn from_editor_no_comments ( filename_safe_intent : & str , initial_text : & str ) -> Result < String > {
12+ let content = from_editor ( filename_safe_intent, initial_text) ?;
1113
1214 // Strip comment lines (starting with '#')
1315 let filtered_lines: Vec < & str > = content
@@ -18,22 +20,25 @@ pub fn from_editor_no_comments(identifier: &str, initial_text: &str) -> Result<S
1820 Ok ( filtered_lines. join ( "\n " ) . trim ( ) . to_string ( ) )
1921}
2022
21- /// Launches the user's preferred text editor to edit some initial text,
22- /// identified by a unique identifier (to avoid temp file collisions).
23- /// Returns the edited text.
23+ /// Launches the user's preferred text editor to edit some `initial_text`,
24+ /// identified by a `filename_safe_intent` to help the user understand what's wanted of them.
25+ /// Note that this string must be valid in filenames.
26+ ///
27+ /// Returns the edited text verbatim.
2428pub fn from_editor ( identifier : & str , initial_text : & str ) -> Result < String > {
2529 let editor_cmd = get_editor_command ( ) ?;
2630
2731 // Create a temporary file with the initial text
28- let temp_dir = std:: env:: temp_dir ( ) ;
29- let temp_file = temp_dir. join ( format ! ( "{}_{}" , identifier, std:: process:: id( ) ) ) ;
30-
31- std:: fs:: write ( & temp_file, initial_text) ?;
32+ let tempfile = tempfile:: Builder :: new ( )
33+ . prefix ( & format ! ( "but_{identifier}_" ) )
34+ . suffix ( ".txt" )
35+ . tempfile ( ) ?;
36+ std:: fs:: write ( & tempfile, initial_text) ?;
3237
3338 // The editor command is allowed to be a shell expression, e.g. "code --wait" is somewhat common.
3439 // We need to execute within a shell to make sure we don't get "No such file or directory" errors.
3540 let status = gix:: command:: prepare ( editor_cmd)
36- . arg ( & temp_file )
41+ . arg ( tempfile . path ( ) )
3742 . stdin ( std:: process:: Stdio :: inherit ( ) )
3843 . stdout ( std:: process:: Stdio :: inherit ( ) )
3944 . with_shell ( )
@@ -43,11 +48,7 @@ pub fn from_editor(identifier: &str, initial_text: &str) -> Result<String> {
4348 if !status. success ( ) {
4449 return Err ( anyhow:: anyhow!( "Editor exited with non-zero status" ) ) ;
4550 }
46-
47- // Read the edited text back
48- let edited_text = std:: fs:: read_to_string ( & temp_file) ?;
49- std:: fs:: remove_file ( & temp_file) . ok ( ) ; // Best effort to clean up
50- Ok ( edited_text)
51+ Ok ( std:: fs:: read_to_string ( & tempfile) ?)
5152}
5253
5354/// Get the user's preferred editor command.
0 commit comments