diff options
-rw-r--r-- | src/plugins/filesystem/FileLocator.cpp | 79 | ||||
-rw-r--r-- | src/plugins/filesystem/FileLocator.hpp | 7 | ||||
-rw-r--r-- | test/plugins/filesystem/FileLocatorTest.cpp | 54 | ||||
-rw-r--r-- | testdata/filesystem/autocomplete/a.test | 0 | ||||
-rw-r--r-- | testdata/filesystem/autocomplete/a.test.backup | 0 | ||||
-rw-r--r-- | testdata/filesystem/autocomplete/a.test~ | 0 | ||||
-rw-r--r-- | testdata/filesystem/autocomplete/b.test1 | 0 | ||||
-rw-r--r-- | testdata/filesystem/autocomplete/b.test2 | 0 | ||||
-rw-r--r-- | testdata/filesystem/autocomplete/c | 0 | ||||
-rw-r--r-- | testdata/filesystem/autocomplete/c.test | 0 | ||||
-rw-r--r-- | testdata/filesystem/autocomplete/de | 0 |
11 files changed, 108 insertions, 32 deletions
diff --git a/src/plugins/filesystem/FileLocator.cpp b/src/plugins/filesystem/FileLocator.cpp index 9a39901..d2b4bb6 100644 --- a/src/plugins/filesystem/FileLocator.cpp +++ b/src/plugins/filesystem/FileLocator.cpp @@ -38,6 +38,19 @@ namespace fs = boost::filesystem; namespace ousia { +/** + * Function used internally to ignore backup files when performing auto + * completion. + * + * @param fn is the filename that should be checked for looking like a temporary + * or backup file. + * @return true if the file might be a backup file, false otherwise. + */ +static bool isBackupFile(const std::string fn) +{ + return Utils::endsWith(fn, "~") || Utils::endsWith(fn, "backup"); +} + void FileLocator::addPath(const std::string &path, std::vector<std::string> &paths) { @@ -135,7 +148,7 @@ static bool iteratePaths(const FileLocator::SearchPaths &searchPaths, // Check whether the given resource has an absolute path -- if yes, call the // callback function and do not try any search paths if (dir.is_absolute()) { - return callback(dir, filename); + return callback(dir, filename, dir); } // If the path starts with "./" or "../" only perform relative lookups! @@ -151,7 +164,7 @@ static bool iteratePaths(const FileLocator::SearchPaths &searchPaths, #endif // Concatenate the searchpath with the given directory fs::path curDir = fs::path(*it) / dir; - if (callback(curDir, filename)) { + if (callback(curDir, filename, dir)) { return true; } } @@ -173,7 +186,7 @@ static bool iteratePaths(const FileLocator::SearchPaths &searchPaths, curDir = curDir / dir; // If we already found a fitting resource there, use that. - if (callback(curDir, filename)) { + if (callback(curDir, filename, dir)) { return true; } } @@ -185,23 +198,23 @@ bool FileLocator::doLocate(Resource &resource, const std::string &path, const ResourceType type, const std::string &relativeTo) const { - return iteratePaths( - searchPaths, path, type, relativeTo, - [&](const fs::path &dir, const std::string &filename) -> bool { - // Combine directory and filename - fs::path p = dir / filename; - - // Check whether p exists - if (fs::exists(p) && fs::is_regular_file(p)) { - std::string location = fs::canonical(p).generic_string(); + return iteratePaths(searchPaths, path, type, relativeTo, + [&](const fs::path &dir, const std::string &filename, + const fs::path &) -> bool { + // Combine directory and filename + fs::path p = dir / filename; + + // Check whether p exists + if (fs::exists(p) && fs::is_regular_file(p)) { + std::string location = fs::canonical(p).generic_string(); #ifdef FILELOCATOR_DEBUG_PRINT - std::cout << "FileLocator: Found at " << location << std::endl; + std::cout << "FileLocator: Found at " << location << std::endl; #endif - resource = Resource(true, *this, type, location); - return true; - } - return false; - }); + resource = Resource(true, *this, type, location); + return true; + } + return false; + }); } std::vector<std::string> FileLocator::doAutocomplete( @@ -210,19 +223,39 @@ std::vector<std::string> FileLocator::doAutocomplete( { std::vector<std::string> res; iteratePaths(searchPaths, path, type, relativeTo, - [&](const fs::path &dir, const std::string &filename) -> bool { + [&](const fs::path &dir, const std::string &filename, + const fs::path &originalDir) -> bool { // Make sure the given directory actually is a directory if (!fs::is_directory(dir)) { return false; } + // Check whether the file itself exists -- if yes, return this file + // directly intead of performing any autocomplete + fs::path p = dir / filename; + if (fs::exists(p) && fs::is_regular_file(p)) { + res.push_back((originalDir / filename).generic_string()); + return true; + } + + // Append a point to the filename -- this allows us to only take files + // into acount that actually extend the extension + const std::string fn = filename + "."; + // Iterate over the directory content fs::directory_iterator end; for (fs::directory_iterator it(dir); it != end; it++) { - const std::string fn = it->path().filename().generic_string(); - if (!fn.empty() && fn[fn.size() - 1] != '~' && - Utils::startsWith(fn, filename)) { - res.push_back(it->path().generic_string()); + // Only consider regular files + fs::path p = it->path(); + if (!fs::is_regular_file(p)) { + continue; + } + + // Fetch the filename of the found file, ignore temporary files + const std::string fn2 = it->path().filename().generic_string(); + if (!fn.empty() && !isBackupFile(fn2) && + Utils::startsWith(fn2, fn)) { + res.push_back((originalDir / fn2).generic_string()); } } return !res.empty(); diff --git a/src/plugins/filesystem/FileLocator.hpp b/src/plugins/filesystem/FileLocator.hpp index 14988a8..ad64db8 100644 --- a/src/plugins/filesystem/FileLocator.hpp +++ b/src/plugins/filesystem/FileLocator.hpp @@ -38,11 +38,8 @@ namespace ousia { /** - * @file FileLocator.hpp - * - * This is a FileLocator employing the boost path class for file finding. - * - * @author Benjamin Paassen - bpaassen@techfak.uni-bielefeld.de + * The FileLocator class is an implementation of the abstract ResourceLocator + * interface used to locate resources in the filesystem. */ class FileLocator : public ResourceLocator { public: diff --git a/test/plugins/filesystem/FileLocatorTest.cpp b/test/plugins/filesystem/FileLocatorTest.cpp index 361a3ca..22db926 100644 --- a/test/plugins/filesystem/FileLocatorTest.cpp +++ b/test/plugins/filesystem/FileLocatorTest.cpp @@ -18,6 +18,8 @@ #include <gtest/gtest.h> +#include <set> + #include <plugins/filesystem/FileLocator.hpp> #include <plugins/filesystem/SpecialPaths.hpp> @@ -142,10 +144,11 @@ TEST(FileLocator, locate) assert_not_located(locator, "c.txt", "", ResourceType::SCRIPT); } -TEST(FileLocator, locateAbsolute){ +TEST(FileLocator, locateAbsolute) +{ FileLocator locator; - // construct the absolute path by utilizing SpecialPaths and - fs::path testdataDir {SpecialPaths::getDebugTestdataDir()}; + // construct the absolute path by utilizing SpecialPaths and + fs::path testdataDir{SpecialPaths::getDebugTestdataDir()}; fs::path absolute = fs::canonical(testdataDir); absolute /= "filesystem"; absolute /= "a.txt"; @@ -217,7 +220,50 @@ TEST(FileLocator, testDefaultSearchPaths) assert_located(locator, "domain/book.osxml", "", ResourceType::UNKNOWN); assert_located(locator, "book.osxml", "", ResourceType::DOMAIN_DESC); assert_not_located(locator, "color.osxml", "", ResourceType::UNKNOWN); - assert_located(locator, "typesystem/color.osxml", "", ResourceType::UNKNOWN); + assert_located(locator, "typesystem/color.osxml", "", + ResourceType::UNKNOWN); assert_located(locator, "color.osxml", "", ResourceType::TYPESYSTEM); } + +TEST(FileLocator, autocompleteIgnoreBackupFiles) +{ + FileLocator locator; + locator.addUnittestSearchPath("filesystem"); + + auto res = locator.autocomplete("autocomplete/a"); + ASSERT_EQ(std::vector<std::string>{"autocomplete/a.test"}, res); +} + +TEST(FileLocator, autocompleteAmbiguous) +{ + FileLocator locator; + locator.addUnittestSearchPath("filesystem"); + + auto res = locator.autocomplete("autocomplete/b"); + + std::set<std::string> resSet; + resSet.insert(res.begin(), res.end()); + + ASSERT_EQ( + std::set<std::string>({"autocomplete/b.test1", "autocomplete/b.test2"}), + resSet); +} + +TEST(FileLocator, autocompleteExisting) +{ + FileLocator locator; + locator.addUnittestSearchPath("filesystem"); + + auto res = locator.autocomplete("autocomplete/c"); + ASSERT_EQ(std::vector<std::string>{"autocomplete/c"}, res); +} + +TEST(FileLocator, autocompleteExtensionOnly) +{ + FileLocator locator; + locator.addUnittestSearchPath("filesystem"); + + auto res = locator.autocomplete("autocomplete/d"); + ASSERT_EQ(std::vector<std::string>{}, res); +} } diff --git a/testdata/filesystem/autocomplete/a.test b/testdata/filesystem/autocomplete/a.test new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/testdata/filesystem/autocomplete/a.test diff --git a/testdata/filesystem/autocomplete/a.test.backup b/testdata/filesystem/autocomplete/a.test.backup new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/testdata/filesystem/autocomplete/a.test.backup diff --git a/testdata/filesystem/autocomplete/a.test~ b/testdata/filesystem/autocomplete/a.test~ new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/testdata/filesystem/autocomplete/a.test~ diff --git a/testdata/filesystem/autocomplete/b.test1 b/testdata/filesystem/autocomplete/b.test1 new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/testdata/filesystem/autocomplete/b.test1 diff --git a/testdata/filesystem/autocomplete/b.test2 b/testdata/filesystem/autocomplete/b.test2 new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/testdata/filesystem/autocomplete/b.test2 diff --git a/testdata/filesystem/autocomplete/c b/testdata/filesystem/autocomplete/c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/testdata/filesystem/autocomplete/c diff --git a/testdata/filesystem/autocomplete/c.test b/testdata/filesystem/autocomplete/c.test new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/testdata/filesystem/autocomplete/c.test diff --git a/testdata/filesystem/autocomplete/de b/testdata/filesystem/autocomplete/de new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/testdata/filesystem/autocomplete/de |