diff --git a/doc/pages/changelog.asciidoc b/doc/pages/changelog.asciidoc index b167f1bc..a8af7c11 100644 --- a/doc/pages/changelog.asciidoc +++ b/doc/pages/changelog.asciidoc @@ -10,6 +10,9 @@ released versions. * Menu completions such as command name completion are now auto-inserted on space +* `write -atomic` was replaced with `write -method [replace|overwrite]` to + make both write method available explicitely + == Kakoune 2020.09.01 * The `repl` and `send-text` aliases have been renamed respectively into diff --git a/doc/pages/commands.asciidoc b/doc/pages/commands.asciidoc index be6738a9..d855f285 100644 --- a/doc/pages/commands.asciidoc +++ b/doc/pages/commands.asciidoc @@ -58,7 +58,7 @@ of the file onto the filesystem Otherwise, does nothing. -*write[!]* [-sync] [-atomic] []:: +*write[!]* [-sync] [-method ] []:: *alias* w + write buffer to or use its name if filename is not given. If the file is write-protected, its permissions are temporarily @@ -68,11 +68,20 @@ of the file onto the filesystem *-sync*::: Synchronise the filesystem after the write - *-atomic*::: - Force writing to a temporary file then renaming to the target file - so that the modification appears atomically. + *-method *::: + Enforce write method instead of relying on the `writemethod` option -*write-all* [-sync]:: + `replace`:::: + Write to a temporary file then rename to the target file so that + the modification appears atomically. + + `overwrite`:::: + Open the existing file and overwrite its content with the new + content. + + (See <>) + +*write-all* [-sync] [-method ]:: *alias* wa + write all changed buffers that are associated with a file @@ -82,12 +91,12 @@ of the file onto the filesystem unsaved buffer remaining. If specified, the client exit status will be set to -*write-quit[!]* [-sync] []:: +*write-quit[!]* [-sync] [-method ] []:: *alias* wq + write current buffer and quit current client. If specified, the client exit status will be set to -*write-all-quit* [-sync] []:: +*write-all-quit* [-sync] [-method ] []:: *alias* waq + write all buffers and quit. If specified, the client exit status will be set to diff --git a/rc/tools/clang.kak b/rc/tools/clang.kak index 23637970..7439ffab 100644 --- a/rc/tools/clang.kak +++ b/rc/tools/clang.kak @@ -23,7 +23,7 @@ define-command -params ..1 \ dir=$(mktemp -d "${TMPDIR:-/tmp}"/kak-clang.XXXXXXXX) mkfifo ${dir}/fifo printf %s\\n " - evaluate-commands -no-hooks write -sync -atomic ${dir}/buf + evaluate-commands -no-hooks write -sync -method replace ${dir}/buf evaluate-commands -draft %{ edit! -fifo ${dir}/fifo -debug *clang-output* set-option buffer filetype make diff --git a/src/commands.cc b/src/commands.cc index e453fbf2..aafad24f 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -456,12 +456,21 @@ const CommandDesc force_edit_cmd = { const ParameterDesc write_params{ { { "sync", { false, "force the synchronization of the file onto the filesystem" } }, - { "atomic", { false, "force the writemethod to replace" } }, + { "method", { true, "explicite writemethod (replace|overwrite)" } }, }, ParameterDesc::Flags::SwitchesOnlyAtStart, 0, 1 }; -void do_write_buffer(Context& context, Optional filename, WriteFlags flags, bool atomic = false) +auto parse_write_method(StringView str) +{ + constexpr auto desc = enum_desc(Meta::Type{}); + auto it = find_if(desc, [str](const EnumDesc& d) { return d.name == str; }); + if (it == desc.end()) + throw runtime_error(format("invalid writemethod '{}'", str)); + return it->value; +} + +void do_write_buffer(Context& context, Optional filename, WriteFlags flags, Optional write_method = {}) { Buffer& buffer = context.buffer(); const bool is_file = (bool)(buffer.flags() & Buffer::Flags::File); @@ -477,10 +486,10 @@ void do_write_buffer(Context& context, Optional filename, WriteFlags fla throw runtime_error("cannot overwrite the buffer when in readonly mode"); auto effective_filename = not filename ? buffer.name() : parse_filename(*filename); - auto mode = atomic ? WriteMethod::Replace : context.options()["writemethod"].get(); + auto method = write_method.value_or_compute([&] { return context.options()["writemethod"].get(); }); context.hooks().run_hook(Hook::BufWritePre, effective_filename, context); - write_buffer_to_file(buffer, effective_filename, mode, flags); + write_buffer_to_file(buffer, effective_filename, method, flags); context.hooks().run_hook(Hook::BufWritePost, effective_filename, context); } @@ -491,7 +500,7 @@ void write_buffer(const ParametersParser& parser, Context& context, const ShellC parser.positional_count() > 0 ? parser[0] : Optional{}, (parser.get_switch("sync") ? WriteFlags::Sync : WriteFlags::None) | (force ? WriteFlags::Force : WriteFlags::None), - (bool)parser.get_switch("atomic")); + parser.get_switch("method").map(parse_write_method)); } const CommandDesc write_cmd = { @@ -518,7 +527,7 @@ const CommandDesc force_write_cmd = { write_buffer, }; -void write_all_buffers(const Context& context, bool sync = false, bool atomic = false) +void write_all_buffers(const Context& context, bool sync = false, Optional write_method = {}) { // Copy buffer list because hooks might be creating/deleting buffers Vector> buffers; @@ -532,10 +541,10 @@ void write_all_buffers(const Context& context, bool sync = false, bool atomic = buffer->is_modified()) and !(buffer->flags() & Buffer::Flags::ReadOnly)) { - auto mode = atomic ? WriteMethod::Replace : context.options()["writemethod"].get(); + auto method = write_method.value_or_compute([&] { return context.options()["writemethod"].get(); }); auto flags = sync ? WriteFlags::Sync : WriteFlags::None; buffer->run_hook_in_own_context(Hook::BufWritePre, buffer->name(), context.name()); - write_buffer_to_file(*buffer, buffer->name(), mode, flags); + write_buffer_to_file(*buffer, buffer->name(), method, flags); buffer->run_hook_in_own_context(Hook::BufWritePost, buffer->name(), context.name()); } } @@ -554,7 +563,8 @@ const CommandDesc write_all_cmd = { CommandCompleter{}, [](const ParametersParser& parser, Context& context, const ShellContext&){ write_all_buffers(context, - (bool)parser.get_switch("sync"), (bool)parser.get_switch("atomic")); + (bool)parser.get_switch("sync"), + parser.get_switch("method").map(parse_write_method)); } }; @@ -661,7 +671,9 @@ template void write_quit(const ParametersParser& parser, Context& context, const ShellContext& shell_context) { - do_write_buffer(context, {}, parser.get_switch("sync") ? WriteFlags::Sync : WriteFlags::None); + do_write_buffer(context, {}, + parser.get_switch("sync") ? WriteFlags::Sync : WriteFlags::None, + parser.get_switch("method").map(parse_write_method)); quit(parser, context, shell_context); } @@ -700,7 +712,9 @@ const CommandDesc write_all_quit_cmd = { CommandCompleter{}, [](const ParametersParser& parser, Context& context, const ShellContext& shell_context) { - write_all_buffers(context, (bool)parser.get_switch("sync")); + write_all_buffers(context, + (bool)parser.get_switch("sync"), + parser.get_switch("method").map(parse_write_method)); quit(parser, context, shell_context); } }; diff --git a/src/main.cc b/src/main.cc index 518278a1..fbb074a0 100644 --- a/src/main.cc +++ b/src/main.cc @@ -48,6 +48,7 @@ struct { "» {+u}set-option -remove{} support\n" "» prompts auto select {+i}menu{} completions on space\n" "» explicit completion support ({+b}...{}) in prompts\n" + "» {+u}write -atomic{} was replaced with {+u}write -method {}\n" }, { 20200901, "» daemon mode does not fork anymore\n"