Skip to content

Commit

Permalink
Support setting shared data via XDG_DATA_DIRS and XDG_DATA_HOME
Browse files Browse the repository at this point in the history
In this PR, fcitx5-rime detect shared data using following logic:

If fcitx5-rime can find `rime-data/default.yaml` in `$XDG_DATA_HOME` or
`$XDG_DATA_DIRS` (using `fcitx::fs::StandardPath::scanDirectories`), it
will use it . Otherwise, it use `RIME_DATA_DIR` specified during build
time as fallback.
  • Loading branch information
wrvsrx committed Nov 7, 2024
1 parent fd8bf83 commit 2a77d73
Showing 1 changed file with 45 additions and 9 deletions.
54 changes: 45 additions & 9 deletions src/rimeengine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include <fcitx/statusarea.h>
#include <fcitx/userinterface.h>
#include <fcitx/userinterfacemanager.h>
#include <filesystem>
#include <list>
#include <memory>
#include <rime_api.h>
Expand Down Expand Up @@ -171,21 +172,56 @@ class IMAction : public Action {

bool RimeEngine::firstRun_ = true;

static bool isFileOrLinkToFile(const std::string &path) {
if (fcitx::fs::isreg(path)) {
return true;
}
std::string p = path;
while (fcitx::fs::islnk(p)) {
p = std::filesystem::read_symlink(p);
}
return fcitx::fs::isreg(p);
}

RimeEngine::RimeEngine(Instance *instance)
: instance_(instance), api_(EnsureRimeApi()),
factory_([this](InputContext &ic) { return new RimeState(this, ic); }),
sessionPool_(this, getSharedStatePolicy()) {
if constexpr (isAndroid() || isApple()) {
const auto &sp = fcitx::StandardPath::global();
std::string defaultYaml = sp.locate(fcitx::StandardPath::Type::Data,
"rime-data/default.yaml");
if (defaultYaml.empty()) {

this->sharedDataDir_ = []() -> std::string {
std::string pathToDefault = {};

// First we detect the shared data directory via XDG_DATA_DIRS and
// XDG_DATA_HOME, if not found, we use RIEM_DATA_DIR as fallback. So
// that users can use XDG_DATA_DIRS to override the shared data.

// We don't use fcitx::StandardPath::global().locate() here because we
// also want to detect symlink to "default.yaml"
fcitx::StandardPath::global().scanDirectories(
fcitx::StandardPath::Type::Data,
[&pathToDefault](const std::string &dirPath, bool) {
auto const fullPath = fs::cleanPath(
stringutils::joinPath(dirPath, "rime-data/default.yaml"));
if (!isFileOrLinkToFile(fullPath)) {
return true;
}
pathToDefault = std::move(fullPath);
return false;
});

// Use RIEM_DATA_DIR as fallback
if (pathToDefault.empty() &&
isFileOrLinkToFile(RIME_DATA_DIR "default.yaml")) {
pathToDefault = RIME_DATA_DIR "default.yaml";
}

// If we can't detect the shared data directory, we throw an exception
if (pathToDefault.empty()) {
throw std::runtime_error("Fail to locate shared data directory");
}
sharedDataDir_ = fcitx::fs::dirName(defaultYaml);
} else {
sharedDataDir_ = RIME_DATA_DIR;
}
return fcitx::fs::dirName(pathToDefault);
}();

imAction_ = std::make_unique<IMAction>(this);
instance_->userInterfaceManager().registerAction("fcitx-rime-im",
imAction_.get());
Expand Down

0 comments on commit 2a77d73

Please sign in to comment.