@@ -190,7 +190,11 @@ fn buffer_previous(
190190 Ok(())
191191}
192192
193−fn write_impl(cx: &mut compositor::Context, path: Option<&Cow<str>>) -> anyhow::Result<()> {
193+fn write_impl(
194+ cx: &mut compositor::Context,
195+ path: Option<&Cow<str>>,
196+ force: bool,
197+) -> anyhow::Result<()> {
194198 let jobs = &mut cx.jobs;
195199 let doc = doc_mut!(cx.editor);
196200
@@ -212,7 +216,7 @@ fn write_impl(cx: &mut compositor::Context, path: Option<&Cow<str>>) -> anyhow::
212216 jobs.callback(callback);
213217 shared
214218 });
215− let future = doc.format_and_save(fmt);
219+ let future = doc.format_and_save(fmt, force);
216220 cx.jobs.add(Job::new(future).wait_before_exiting());
217221
218222 if path.is_some() {
@@ -228,7 +232,15 @@ fn write(
228232 args: &[Cow<str>],
229233 _event: PromptEvent,
230234) -> anyhow::Result<()> {
231− write_impl(cx, args.first())
235+ write_impl(cx, args.first(), false)
236+}
237+
238+fn force_write(
239+ cx: &mut compositor::Context,
240+ args: &[Cow<str>],
241+ _event: PromptEvent,
242+) -> anyhow::Result<()> {
243+ write_impl(cx, args.first(), true)
232244}
233245
234246fn new_file(
@@ -381,7 +393,7 @@ fn write_quit(
381393 args: &[Cow<str>],
382394 event: PromptEvent,
383395) -> anyhow::Result<()> {
384− write_impl(cx, args.first())?;
396+ write_impl(cx, args.first(), false)?;
385397 quit(cx, &[], event)
386398}
387399
@@ -390,7 +402,7 @@ fn force_write_quit(
390402 args: &[Cow<str>],
391403 event: PromptEvent,
392404) -> anyhow::Result<()> {
393− write_impl(cx, args.first())?;
405+ write_impl(cx, args.first(), true)?;
394406 force_quit(cx, &[], event)
395407}
396408
@@ -447,7 +459,7 @@ fn write_all_impl(
447459 jobs.callback(callback);
448460 shared
449461 });
450− let future = doc.format_and_save(fmt);
462+ let future = doc.format_and_save(fmt, force);
451463 jobs.add(Job::new(future).wait_before_exiting());
452464 }
453465
@@ -1140,6 +1152,13 @@ pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
11401152 fun: write,
11411153 completer: Some(completers::filename),
11421154 },
1155+ TypableCommand {
1156+ name: "write!",
1157+ aliases: &["w!"],
1158+ doc: "Write changes to disk forcefully (creating necessary subdirectories). Accepts an optional path (:write some/path.txt)",
1159+ fun: force_write,
1160+ completer: Some(completers::filename),
1161+ },
11431162 TypableCommand {
11441163 name: "new",
11451164 aliases: &["n"],