summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxime Coste <frrrwww@gmail.com>2016-07-24 21:21:49 +0100
committerMaxime Coste <frrrwww@gmail.com>2016-07-24 21:21:49 +0100
commit003cb8dfea517e5d1dfbfc844e875ce2995b6e74 (patch)
tree830a7d20efa155861846a07d204a80394fcb49f6 /src
parenta95937918d243a6811a37f59a80ef8665896122a (diff)
parente3bf01d1f9063fa25ae0f0b104eb1539d0e941b6 (diff)
Merge remote-tracking branch 'lenormf/readonly-mode'
Diffstat (limited to 'src')
-rw-r--r--src/buffer.cc7
-rw-r--r--src/buffer.hh13
-rw-r--r--src/buffer_manager.cc3
-rw-r--r--src/commands.cc9
-rw-r--r--src/main.cc30
5 files changed, 46 insertions, 16 deletions
diff --git a/src/buffer.cc b/src/buffer.cc
index df9a7613..51be811f 100644
--- a/src/buffer.cc
+++ b/src/buffer.cc
@@ -606,6 +606,13 @@ void Buffer::set_fs_timestamp(timespec ts)
void Buffer::on_option_changed(const Option& option)
{
+ if (option.name() == "readonly")
+ {
+ if (option.get<bool>())
+ m_flags |= Flags::ReadOnly;
+ else
+ m_flags &= ~Flags::ReadOnly;
+ }
run_hook_in_own_context("BufSetOption",
format("{}={}", option.name(), option.get_as_string()));
}
diff --git a/src/buffer.hh b/src/buffer.hh
index 98806296..e84c14e0 100644
--- a/src/buffer.hh
+++ b/src/buffer.hh
@@ -101,12 +101,13 @@ class Buffer : public SafeCountable, public OptionManagerWatcher, public Scope
public:
enum class Flags
{
- None = 0,
- File = 1 << 0,
- New = 1 << 1,
- Fifo = 1 << 2,
- NoUndo = 1 << 3,
- Debug = 1 << 4
+ None = 0,
+ File = 1 << 0,
+ New = 1 << 1,
+ Fifo = 1 << 2,
+ NoUndo = 1 << 3,
+ Debug = 1 << 4,
+ ReadOnly = 1 << 5,
};
Buffer(String name, Flags flags, StringView data = {},
diff --git a/src/buffer_manager.cc b/src/buffer_manager.cc
index 98dfc7f1..79546d53 100644
--- a/src/buffer_manager.cc
+++ b/src/buffer_manager.cc
@@ -87,7 +87,8 @@ void BufferManager::backup_modified_buffers()
{
for (auto& buf : m_buffers)
{
- if ((buf->flags() & Buffer::Flags::File) and buf->is_modified())
+ if ((buf->flags() & Buffer::Flags::File) and buf->is_modified()
+ and not (buf->flags() & Buffer::Flags::ReadOnly))
write_buffer_to_backup_file(*buf);
}
}
diff --git a/src/commands.cc b/src/commands.cc
index 0a13938e..fa61a8c4 100644
--- a/src/commands.cc
+++ b/src/commands.cc
@@ -239,6 +239,12 @@ void write_buffer(const ParametersParser& parser, Context& context, const ShellC
if (parser.positional_count() == 0 and !(buffer.flags() & Buffer::Flags::File))
throw runtime_error("cannot write a non file buffer without a filename");
+ // if the buffer is in read-only mode and we try to save it directly
+ // or we try to write to it indirectly using e.g. a symlink, throw an error
+ if ((context.buffer().flags() & Buffer::Flags::ReadOnly)
+ and (parser.positional_count() == 0 or real_path(parser[0]) == buffer.name()))
+ throw runtime_error("cannot overwrite the buffer when in readonly mode");
+
auto filename = parser.positional_count() == 0 ?
buffer.name() : parse_filename(parser[0]);
write_buffer_to_file(buffer, filename);
@@ -260,7 +266,8 @@ void write_all_buffers()
{
for (auto& buffer : BufferManager::instance())
{
- if ((buffer->flags() & Buffer::Flags::File) and buffer->is_modified())
+ if ((buffer->flags() & Buffer::Flags::File) and buffer->is_modified()
+ and !(buffer->flags() & Buffer::Flags::ReadOnly))
write_buffer_to_file(*buffer, buffer->name());
}
}
diff --git a/src/main.cc b/src/main.cc
index 2ebeb632..2a72d423 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -265,6 +265,7 @@ void register_options()
reg.declare_option("modelinefmt", "format string used to generate the modeline",
"%val{bufname} %val{cursor_line}:%val{cursor_char_column} "_str);
reg.declare_option("debug", "various debug flags", DebugFlags::None);
+ reg.declare_option("readonly", "prevent buffers from being modified", false);
}
struct convert_to_client_mode
@@ -460,7 +461,7 @@ int run_client(StringView session, StringView init_command, UIType ui_type)
}
int run_server(StringView session, StringView init_command,
- bool ignore_kakrc, bool daemon, UIType ui_type,
+ bool ignore_kakrc, bool daemon, bool readonly, UIType ui_type,
ConstArrayView<StringView> files, ByteCoord target_coord)
{
static bool terminate = false;
@@ -503,6 +504,8 @@ int run_server(StringView session, StringView init_command,
write_to_debug_buffer("*** This is the debug buffer, where debug info will be written ***");
+ GlobalScope::instance().options().get_local_option("readonly").set(readonly);
+
Server server(session.empty() ? to_string(getpid()) : session.str());
bool startup_error = false;
@@ -536,7 +539,9 @@ int run_server(StringView session, StringView init_command,
{
try
{
- open_or_create_file_buffer(file);
+ Buffer *buffer = open_or_create_file_buffer(file);
+ if (readonly)
+ buffer->flags() |= Buffer::Flags::ReadOnly;
}
catch (Kakoune::runtime_error& error)
{
@@ -741,7 +746,8 @@ int main(int argc, char* argv[])
{ "q", { false, "in filter mode, be quiet about errors applying keys" } },
{ "ui", { true, "set the type of user interface to use (ncurses, dummy, or json)" } },
{ "l", { false, "list existing sessions" } },
- { "clear", { false, "clear dead sessions" } } }
+ { "clear", { false, "clear dead sessions" } },
+ { "ro", { false, "readonly mode" } } }
};
try
{
@@ -773,11 +779,11 @@ int main(int argc, char* argv[])
if (auto session = parser.get_switch("p"))
{
- for (auto opt : { "c", "n", "s", "d", "e" })
+ for (auto opt : { "c", "n", "s", "d", "e", "ro" })
{
if (parser.get_switch(opt))
{
- write_stderr(format("error: -{} makes not sense with -p\n", opt));
+ write_stderr(format("error: -{} is incompatible with -p\n", opt));
return -1;
}
}
@@ -789,20 +795,27 @@ int main(int argc, char* argv[])
if (auto keys = parser.get_switch("f"))
{
+ if (parser.get_switch("ro"))
+ {
+ write_stderr("error: -ro is incompatible with -f\n");
+ return -1;
+ }
+
Vector<StringView> files;
for (size_t i = 0; i < parser.positional_count(); ++i)
files.emplace_back(parser[i]);
- return run_filter(*keys, init_command, files, (bool)parser.get_switch("q"));
+ return run_filter(*keys, init_command, files,
+ (bool)parser.get_switch("q"));
}
if (auto server_session = parser.get_switch("c"))
{
- for (auto opt : { "n", "s", "d" })
+ for (auto opt : { "n", "s", "d", "ro" })
{
if (parser.get_switch(opt))
{
- write_stderr(format("error: -{} makes not sense with -c\n", opt));
+ write_stderr(format("error: -{} is incompatible with -c\n", opt));
return -1;
}
}
@@ -840,6 +853,7 @@ int main(int argc, char* argv[])
return run_server(session, init_command,
(bool)parser.get_switch("n"),
(bool)parser.get_switch("d"),
+ (bool)parser.get_switch("ro"),
ui_type, files, target_coord);
}
catch (convert_to_client_mode& convert)