diff --git a/src/rime/gear/schema_list_translator.cc b/src/rime/gear/schema_list_translator.cc index 3e58fe308..b44985cff 100644 --- a/src/rime/gear/schema_list_translator.cc +++ b/src/rime/gear/schema_list_translator.cc @@ -98,9 +98,6 @@ void SchemaListTranslation::LoadSchemaList(Switcher* switcher) { Config* config = switcher->schema()->config(); if (!config) return; - auto schema_list = config->GetList("schema_list"); - if (!schema_list) - return; // current schema comes first Schema* current_schema = engine->schema(); if (current_schema) { @@ -110,27 +107,23 @@ void SchemaListTranslation::LoadSchemaList(Switcher* switcher) { size_t fixed = candies_.size(); time_t now = time(NULL); // load the rest schema list - for (size_t i = 0; i < schema_list->size(); ++i) { - auto item = As(schema_list->GetAt(i)); - if (!item) - continue; - auto schema_property = item->GetValue("schema"); - if (!schema_property) - continue; - const string& schema_id(schema_property->str()); - if (current_schema && schema_id == current_schema->schema_id()) - continue; - Schema schema(schema_id); - auto cand = New(&schema); - int timestamp = 0; - if (user_config && - user_config->GetInt("var/schema_access_time/" + schema_id, - ×tamp)) { - if (timestamp <= now) - cand->set_quality(timestamp); - } - Append(cand); - } + Switcher::ForEachSchemaListEntry( + config, + [this, current_schema, user_config, now](const string& schema_id) { + if (current_schema && schema_id == current_schema->schema_id()) + return /* continue = */true; + Schema schema(schema_id); + auto cand = New(&schema); + int timestamp = 0; + if (user_config && + user_config->GetInt("var/schema_access_time/" + schema_id, + ×tamp)) { + if (timestamp <= now) + cand->set_quality(timestamp); + } + Append(cand); + return /* continue = */true; + }); DLOG(INFO) << "num schemata: " << candies_.size(); bool fix_order = false; config->GetBool("switcher/fix_schema_list_order", &fix_order); diff --git a/src/rime/switcher.cc b/src/rime/switcher.cc index ae53918d0..088fe8770 100644 --- a/src/rime/switcher.cc +++ b/src/rime/switcher.cc @@ -108,35 +108,88 @@ void Switcher::HighlightNextSchema() { return; } +/* + Example configuration: + + ```yaml + schema_list: + - case: [mode/wubi, mode/wubi_pinyin] + schema: wubi_pinyin + - case: [mode/wubi] + schema: wubi86 + - case: [mode/default] + schema: pinyin + + mode: + wubi: false + wubi_pinyin: false + default: true + ``` +*/ + +static an ParseSchemaListEntry(Config* config, + an entry_map) { + if (!entry_map) + return nullptr; + auto schema_property = entry_map->GetValue("schema"); + if (!schema_property) + return nullptr; + if (auto case_conditions = As(entry_map->Get("case"))) { + for (auto iter = case_conditions->begin(); + iter != case_conditions->end(); + ++iter) { + if (auto condition_variable = As(*iter)) { + bool condition_met = false; + if (!config->GetBool(condition_variable->str(), &condition_met) || + !condition_met) { + return nullptr; + } + } + } + } + return schema_property; +} + +int Switcher::ForEachSchemaListEntry( + Config* config, function process_entry) { + auto schema_list = config->GetList("schema_list"); + if (!schema_list) + return 0; + int num_processed_entries = 0; + for (auto iter = schema_list->begin(); iter != schema_list->end(); ++iter) { + auto entry = ParseSchemaListEntry(config, As(*iter)); + if (!entry) + continue; + const string& schema_id = entry->str(); + ++num_processed_entries; + if (!process_entry(schema_id)) + break; + } + return num_processed_entries; +} + Schema* Switcher::CreateSchema() { Config* config = schema_->config(); if (!config) - return NULL; - auto schema_list = config->GetList("schema_list"); - if (!schema_list) - return NULL; + return nullptr; string previous; - if (user_config_) { + if (user_config_ && !fix_schema_list_order_) { user_config_->GetString("var/previously_selected_schema", &previous); } string recent; - for (size_t i = 0; i < schema_list->size(); ++i) { - auto item = As(schema_list->GetAt(i)); - if (!item) - continue; - auto schema_property = item->GetValue("schema"); - if (!schema_property) - continue; - const string& schema_id(schema_property->str()); - if (previous.empty() || previous == schema_id) { - recent = schema_id; - break; - } - if (recent.empty()) - recent = schema_id; - } + ForEachSchemaListEntry( + config, + [&previous, &recent](const string& schema_id) { + if (previous.empty() || previous == schema_id) { + recent = schema_id; + return /* continue = */false; + } + if (recent.empty()) + recent = schema_id; + return /* continue = */true; + }); if (recent.empty()) - return NULL; + return nullptr; else return new Schema(recent); } @@ -225,6 +278,7 @@ void Switcher::LoadSettings() { } } config->GetBool("switcher/fold_options", &fold_options_); + config->GetBool("switcher/fix_schema_list_order", &fix_schema_list_order_); } void Switcher::InitializeComponents() { diff --git a/src/rime/switcher.h b/src/rime/switcher.h index 7172cc641..e4246843b 100644 --- a/src/rime/switcher.h +++ b/src/rime/switcher.h @@ -27,6 +27,9 @@ class Switcher : public Processor, public Engine { } virtual ProcessResult ProcessKeyEvent(const KeyEvent& key_event); + static int ForEachSchemaListEntry( + Config* config, function process_entry); + Schema* CreateSchema(); void SelectNextSchema(); bool IsAutoSave(const string& option) const; @@ -51,6 +54,7 @@ class Switcher : public Processor, public Engine { vector hotkeys_; set save_options_; bool fold_options_ = false; + bool fix_schema_list_order_ = false; vector> processors_; vector> translators_;