rust: Passing regulate to the person’s favourite editor (akin to VSCode) from the CLI

What person revel in do we would like for the
act of writing?

We’ve a couple of choices, together with letting
customers write without delay within the console or giving
them a ready report that they are able to then open
and write in.

Writing without delay within the console does not give
a person get admission to to their textual content editor of selection.
Which means that missing autocomplete, syntax
highlighting, snippets, and different capability.

Making a report and dealing with the trail again to
the person does not moderately paintings for us both, as
that reduces the application of the lawn write
command to the similar of operating contact
filename.md
.

So for our use case, we would preferably love to open
the person’s most popular enhancing surroundings,
no matter that occurs to be, then look forward to them
to be completed with the report ahead of proceeding.

Since we are operating with a CLI instrument, we
can safely think that our customers both
understand how to, or are willingly to be told how
to, set surroundings variables. This implies we
can use the EDITOR variable to choose an
editor to make use of. This is identical manner git dedicate
works.


In Rust, there’s a crate that handles now not most effective
EDITOR, but additionally quite a lot of fallbacks per-platform.
We’re going to benefit from (*2*)edit
to name out to the person’s selection of editor.

The fast utilization of edit permits us to name the
edit::edit serve as, and get the person’s knowledge.

pub fn write(garden_path: PathBuf, identify: Choice<String>) -> End result<()> { dbg!(garden_path, identify); let template = "# "; let content_from_user = edit::edit(template).wrap_err("not able to learn writing")?; dbg!(content_from_user); todo!()
}

This leads to a filename that appears like:
.tmpBy0Yun “in other places” at the filesystem,
in a location the person would by no means moderately
in finding it. Preferably, if anything else went improper, the
person could be in a position to try the
in-progress tempfile they have been simply operating on,
which must be in an simply discoverable position
just like the lawn trail.

We do not need to lose a person’s paintings.

Moreover, the tempfile does not have a report
extension, which means that that the person’s editor
can be much less prone to acknowledge it as a
markdown report, so we need to upload .md to the
filepath.

use color_eyre::{eyre::WrapErr, End result};
use edit::{edit_file, Builder};
use std::io::{Learn, Write};
use std::trail::PathBuf; const TEMPLATE: &(*5*) = b"# "; pub fn write(garden_path: PathBuf, identify: Choice<String>) -> End result<()> { let (mut report, filepath) = Builder::new() .suffix(".md") .rand_bytes(5) .tempfile_in(&garden_path) .wrap_err("Did not create wip report")? .stay() .wrap_err("Did not stay tempfile")?; report.write_all(TEMPLATE)?; // let the person write no matter they would like of their favourite editor // ahead of returning to the cli and completing up edit_file(filepath)?; // Learn the person's adjustments again from the report right into a string let mut contents = String::new(); report.read_to_string(&mut contents)?; dbg!(contents); todo!()
}

We can use the edit::Builder API to generate
a random tempfile to let the person write content material
into. The suffix goes to be .md and the
filename can be 5 random bytes. We additionally put
the tempfile within the lawn trail, which guarantees
a person will have the ability to in finding it if vital.

wrap_err (which calls for the eyre::WrapErr
trait in scope) wraps the possible error
as a result of those calls with further context,
making the unique error the supply, and we will
stay chaining after that. We stay the tempfile,
which might another way be deleted when all handles
closed, as a result of if anything else is going improper after the
person inputs knowledge, we need to make certain we do not
lose that knowledge.

After the report is created, we write our template
out to the report ahead of passing regulate to the
person. This calls for the std::io::Write trait
in scope. We use a const for the report template
as it may not alternate. To make the TEMPLATE
a const, we additionally want to give it a kind, which
is a two component byte array. Alternate the string
to peer how the byte array period is checked at
bring together time.

Since we have now get admission to to the report already, we
can learn the contents again right into a string after
the person is completed enhancing. This calls for having
the std::io::Learn trait in scope.

And now we now have let the person write right into a report
which is able to stick round so long as we want it
to, and importantly will stick round if any
mistakes occur within the execution of this system,
so we lose no person knowledge and will take away the
transient report on the finish of this system
ourselves if all is going neatly.