diff --git a/src/file.cc b/src/file.cc index f4db41b6..49a1e6ab 100644 --- a/src/file.cc +++ b/src/file.cc @@ -48,14 +48,21 @@ public: : runtime_error(format("fd {}: {}", fd, error_desc)) {} }; -String parse_filename(StringView filename) +String parse_filename(StringView filename, StringView buf_dir) { auto prefix = filename.substr(0_byte, 2_byte); if (prefix == "~" or prefix == "~/") return homedir() + filename.substr(1_byte); + if ((prefix == "%" or prefix == "%/") and not buf_dir.empty()) + return buf_dir + filename.substr(1_byte); return filename.str(); } +String parse_filename(StringView filename) +{ + return parse_filename(filename, {}); +} + std::pair split_path(StringView path) { auto it = find(path | reverse(), '/'); @@ -331,7 +338,7 @@ void write_buffer_to_backup_file(Buffer& buffer) } } -String find_file(StringView filename, ConstArrayView paths) +String find_file(StringView filename, StringView buf_dir, ConstArrayView paths) { struct stat buf; if (filename.substr(0_byte, 1_byte) == "/") @@ -348,7 +355,7 @@ String find_file(StringView filename, ConstArrayView paths) return ""; } - for (auto candidate : paths | transform(parse_filename)) + for (auto candidate : paths | transform([&](StringView s) { return parse_filename(s, buf_dir); })) { if (not candidate.empty() and candidate.back() != '/') candidate += '/'; diff --git a/src/file.hh b/src/file.hh index 232ff539..5986ab2f 100644 --- a/src/file.hh +++ b/src/file.hh @@ -19,8 +19,10 @@ class Regex; using CandidateList = Vector; -// parse ~/ and $env values in filename and returns the translated filename +// parse ~/ and %/ in filename and returns the translated filename +String parse_filename(StringView filename, StringView buf_dir); String parse_filename(StringView filename); + String real_path(StringView filename); String compact_path(StringView filename); @@ -54,7 +56,7 @@ void write_buffer_to_file(Buffer& buffer, StringView filename, bool force = fals void write_buffer_to_fd(Buffer& buffer, int fd); void write_buffer_to_backup_file(Buffer& buffer); -String find_file(StringView filename, ConstArrayView paths); +String find_file(StringView filename, StringView buf_dir, ConstArrayView paths); bool file_exists(StringView filename); Vector list_files(StringView directory); diff --git a/src/insert_completer.cc b/src/insert_completer.cc index 5bd1efe7..8db65556 100644 --- a/src/insert_completer.cc +++ b/src/insert_completer.cc @@ -246,6 +246,13 @@ InsertCompletion complete_filename(const SelectionList& sels, { if (not dir.empty() and dir.back() != '/') dir += '/'; + if (dir.substr(0, 2_byte) == "%/") + { + if (not (buffer.flags() & Buffer::Flags::File)) + continue; + dir = split_path(buffer.name()).first.str() + '/' + dir.substr(2_byte); + } + for (auto& filename : Kakoune::complete_filename(dir + prefix, options["ignored_files"].get())) { diff --git a/src/main.cc b/src/main.cc index f1ae9f81..3ac73b42 100644 --- a/src/main.cc +++ b/src/main.cc @@ -323,7 +323,7 @@ void register_options() Regex{}); reg.declare_option("filetype", "buffer filetype", ""_str); reg.declare_option("path", "path to consider when trying to find a file", - Vector({ "./", "/usr/include" })); + Vector({ "./", "%/", "/usr/include" })); reg.declare_option("completers", "insert mode completers to execute.", InsertCompleterDescList({ InsertCompleterDesc{ InsertCompleterDesc::Filename, {} }, diff --git a/src/normal.cc b/src/normal.cc index 05a5246e..968293b6 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -278,11 +278,8 @@ void goto_commands(Context& context, NormalParams params) return; auto paths = context.options()["path"].get>(); - StringView buffer_dir = split_path(buffer.name()).first; - if (not buffer_dir.empty()) - paths.insert(paths.begin(), buffer_dir.str()); - - String path = find_file(filename, paths); + const StringView buffer_dir = split_path(buffer.name()).first; + String path = find_file(filename, buffer_dir, paths); if (path.empty()) throw runtime_error(format("unable to find file '{}'", filename));