diff --git a/src/file.cc b/src/file.cc index 2e105d16..eb01081d 100644 --- a/src/file.cc +++ b/src/file.cc @@ -13,6 +13,40 @@ namespace Kakoune { +bool isidentifier(char c) +{ + return std::isalnum(c) or c == '_'; +} + +std::string parse_filename(const std::string& filename) +{ + if (filename.length() > 2 and filename[0] == '~' and filename[1] == '/') + return parse_filename("$HOME/" + filename.substr(2)); + + size_t pos = 0; + std::string result; + for (size_t i = 0; i < filename.length(); ++i) + { + if (filename[i] == '$' and (i == 0 or filename[i-1] != '\\')) + { + result += filename.substr(pos, i - pos); + size_t end = i+1; + while (end != filename.length() and isidentifier(filename[end])) + ++end; + std::string var_name = filename.substr(i+1, end - i - 1); + const char* var_value = getenv(var_name.c_str()); + if (var_value) + result += var_value; + + pos = end; + } + } + if (pos != filename.length()) + result += filename.substr(pos); + + return result; +} + std::string read_file(const std::string& filename) { int fd = open(filename.c_str(), O_RDONLY); diff --git a/src/file.hh b/src/file.hh index b6b7fc6a..3f1c599b 100644 --- a/src/file.hh +++ b/src/file.hh @@ -23,6 +23,10 @@ struct file_not_found : file_access_error }; class Buffer; + +// parse ~/ and $env values in filename and returns the translated filename +std::string parse_filename(const std::string& filename); + std::string read_file(const std::string& filename); Buffer* create_buffer_from_file(const std::string& filename); void write_buffer_to_file(const Buffer& buffer, const std::string& filename); diff --git a/src/main.cc b/src/main.cc index f1a6cdef..d0164737 100644 --- a/src/main.cc +++ b/src/main.cc @@ -535,7 +535,8 @@ void write_buffer(const CommandParameters& params, const Context& context) throw wrong_argument_count(); Buffer& buffer = context.window().buffer(); - std::string filename = params.empty() ? buffer.name() : params[0]; + std::string filename = params.empty() ? buffer.name() + : parse_filename(params[0]); write_buffer_to_file(buffer, filename); buffer.notify_saved(); @@ -695,7 +696,7 @@ void exec_commands_in_file(const CommandParameters& params, if (params.size() != 1) throw wrong_argument_count(); - std::string file_content = read_file(params[0]); + std::string file_content = read_file(parse_filename(params[0])); CommandManager& cmd_manager = CommandManager::instance(); size_t pos = 0;