diff --git a/Cargo.lock b/Cargo.lock index 4cc42ba..4d81956 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,10 +26,13 @@ dependencies = [ name = "akaza-conf" version = "0.1.7" dependencies = [ + "anyhow", "env_logger", "gtk4", "libakaza", "log", + "serde", + "serde_yaml", "xdg", ] @@ -1533,9 +1536,9 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.16" +version = "0.9.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92b5b431e8907b50339b51223b97d102db8d987ced36f6e4d03621db9316c834" +checksum = "8fb06d4b6cdaef0e0c51fa881acb721bed3c924cfaa71d9c94a3b771dfdf6567" dependencies = [ "indexmap", "itoa", diff --git a/Changes.md b/Changes.md index a2ebccd..24d4926 100644 --- a/Changes.md +++ b/Changes.md @@ -1,3 +1,7 @@ +# 2023-01-24(Tue) + +* 設定画面を gtk4-rs で実装した。 + # 2022-12-23(Fri) * Started development, again. diff --git a/README.md b/README.md index 4cadeb2..fdc1137 100644 --- a/README.md +++ b/README.md @@ -56,36 +56,6 @@ ibus-akaza をインストールしてください。 ## 設定方法 -### config.yml - -XDG の設定ファイルディレクトリ以下、通常であれば `$HOME/.config/akaza/config.yml` に設定ファイルを書くことができます。 - -設定可能な項目は以下のもの。 - -* ユーザー辞書の設定 - -サンプルの設定は以下のような感じになります。 -akaza が提供しているシステム辞書は偏りがすごくあるので、SKK-JISYO.L を読み込むことをおすすめします。たとえば以下のように設定すると良いでしょう。 - - --- - dicts: - - path: /usr/share/skk/SKK-JISYO.L - encoding: EucJp - dict_type: SKK - - path: /usr/share/skk/SKK-JISYO.jinmei - encoding: EucJp - dict_type: SKK - single_term: - - path: /usr/share/akaza/SKK-JISYO.dynamic - encoding: Utf8 - dict_type: SKK - -akaza に付属する SKK-JISYO.dynamic を利用すると、「きょう」を変換すると、今日の日付がでるという機能が利用可能です。 - -↓ かな入力したい場合は以下のように設定してください。 - - romkan: kana - ### Keymap の設定 Akaza は典型的には以下の順番で探します。 diff --git a/akaza-conf/Cargo.toml b/akaza-conf/Cargo.toml index a2a9edc..3871daf 100644 --- a/akaza-conf/Cargo.toml +++ b/akaza-conf/Cargo.toml @@ -10,3 +10,6 @@ xdg = "2.4.1" log = "0.4.17" env_logger = "0.10.0" libakaza = { path = "../libakaza" } +anyhow = "1.0.68" +serde = "1.0.152" +serde_yaml = "0.9.17" diff --git a/akaza-conf/src/conf.rs b/akaza-conf/src/conf.rs index 2554b3b..a5d3b7a 100644 --- a/akaza-conf/src/conf.rs +++ b/akaza-conf/src/conf.rs @@ -1,65 +1,109 @@ use std::path::PathBuf; +use std::process::Command; +use std::sync::{Arc, Mutex}; +use anyhow::Result; use gtk::glib::signal::Inhibit; use gtk::prelude::*; use gtk::{Application, ApplicationWindow, Button, Label, Notebook}; use gtk4 as gtk; -use gtk4::builders::ComboBoxTextBuilder; use gtk4::gio::ApplicationFlags; use gtk4::{ComboBoxText, Grid}; -use libakaza::config::Config; -use log::info; +use log::{error, info}; -pub fn open_configuration_window() { +use libakaza::config::{Config, DictUsage}; + +pub fn open_configuration_window() -> Result<()> { + let config = Arc::new(Mutex::new(Config::load()?)); let app = Application::new(Some("com.github.akaza.config"), ApplicationFlags::empty()); - app.connect_activate(|app| { - let window = ApplicationWindow::builder() - .application(app) - .default_width(320) - .default_height(200) - .title("Akaza の設定") - .build(); - - let notebook = Notebook::builder().build(); - notebook.append_page(&build_core_pane(), Some(&Label::new(Some("基本設定")))); - notebook.append_page(&build_dict_pane(), Some(&Label::new(Some("辞書")))); - notebook.append_page(&build_about_pane(), Some(&Label::new(Some("アバウト")))); - - let grid = Grid::builder().build(); - - grid.attach(¬ebook, 0, 0, 6, 1); - - let ok_button = Button::with_label("OK"); - ok_button.connect_clicked(|_| { - eprintln!("Save the configuration..."); - // TODO: 保存処理 - }); - let cancel_button = Button::with_label("Cancel"); - { - let window_clone = window.clone(); - cancel_button.connect_clicked(move |_| { - eprintln!("Close the configuration window!"); - window_clone.close(); - }); - } - grid.attach(&ok_button, 4, 1, 1, 1); - grid.attach(&cancel_button, 5, 1, 1, 1); - - window.set_child(Some(&grid)); - - window.connect_close_request(move |window| { - if let Some(application) = window.application() { - application.remove_window(window); - } - Inhibit(false) - }); - - window.show(); + app.connect_activate(move |app| { + connect_activate(app, config.clone()).unwrap(); }); let v: Vec = Vec::new(); app.run_with_args(v.as_slice()); + Ok(()) +} + +fn connect_activate(app: &Application, config: Arc>) -> Result<()> { + let window = ApplicationWindow::builder() + .application(app) + .default_width(320) + .default_height(200) + .title("Akaza の設定") + .build(); + + let notebook = Notebook::builder().build(); + notebook.append_page( + &build_core_pane(config.clone())?, + Some(&Label::new(Some("基本設定"))), + ); + notebook.append_page( + &build_dict_pane(config.clone()), + Some(&Label::new(Some("辞書"))), + ); + notebook.append_page(&build_about_pane(), Some(&Label::new(Some("アバウト")))); + + let grid = Grid::builder().build(); + + grid.attach(¬ebook, 0, 0, 6, 1); + + let ok_button = Button::with_label("OK"); + let config = config; + ok_button.connect_clicked(move |_| { + eprintln!("Save the configuration..."); + // TODO: 保存処理 + let config = config.lock().unwrap(); + let config = Config { + keymap: config.keymap.to_string(), + romkan: config.romkan.to_string(), + model: config.model.to_string(), + dicts: config.dicts.clone(), + }; + info!("Saving config: {}", serde_yaml::to_string(&config).unwrap()); + + config.save().unwrap(); + + // 最後に ibus restart をしちゃおう。設定の再読み込みとか実装するのは大変。 + let output = Command::new("ibus").arg("restart").output().unwrap(); + + if !output.status.success() { + error!( + "Cannot run `ibus restart`: out={}, err={}", + String::from_utf8(output.stdout).unwrap(), + String::from_utf8(output.stderr).unwrap() + ); + } else { + info!( + "Ran `ibus restart`: out={}, err={}", + String::from_utf8(output.stdout).unwrap(), + String::from_utf8(output.stderr).unwrap() + ); + } + }); + let cancel_button = Button::with_label("Cancel"); + { + let window_clone = window.clone(); + cancel_button.connect_clicked(move |_| { + eprintln!("Close the configuration window!"); + window_clone.close(); + }); + } + grid.attach(&ok_button, 4, 1, 1, 1); + grid.attach(&cancel_button, 5, 1, 1, 1); + + window.set_child(Some(&grid)); + + window.connect_close_request(move |window| { + if let Some(application) = window.application() { + application.remove_window(window); + } + Inhibit(false) + }); + + window.show(); + Ok(()) } #[derive(Debug)] @@ -68,7 +112,7 @@ struct PathConfItem { path: String, } -fn get_keymap_list

(path: &str, filter: P) -> Vec +fn get_list

(path: &str, filter: P) -> Vec where P: FnMut(&&PathBuf) -> bool, { @@ -85,13 +129,14 @@ where .unwrap() .to_str() .unwrap() - .to_string(), + .to_string() + .replace(".yml", ""), path: f.to_string_lossy().to_string(), }) .collect::>() } -fn build_core_pane() -> Grid { +fn build_core_pane(config: Arc>) -> anyhow::Result { // キーマップとローマ字テーブル、モデルの設定ができるようにする。 let grid = Grid::new(); // xalign: 0 は左寄という意味。 @@ -104,13 +149,20 @@ fn build_core_pane() -> Grid { ); grid.attach( &{ - //TODO: 設定ファイルに書いてあるものを default value として選ぶ let cbt = ComboBoxText::new(); - let romkan = get_keymap_list("keymap", { |f| f.to_string_lossy().ends_with(".yml") }); - info!("keymap: {:?}", romkan); - for item in romkan { + let keymap = get_list("keymap", { |f| f.to_string_lossy().ends_with(".yml") }); + for item in keymap { cbt.append(Some(&item.path), &item.name); } + cbt.set_active_id(Some(&config.lock().unwrap().keymap)); + { + let config = config.clone(); + cbt.connect_changed(move |f| { + if let Some(id) = f.active_id() { + config.lock().unwrap().keymap = id.to_string(); + } + }); + } cbt }, 1, @@ -131,11 +183,20 @@ fn build_core_pane() -> Grid { grid.attach( &{ let cbt = ComboBoxText::new(); - let romkan = get_keymap_list("romkan", { |f| f.to_string_lossy().ends_with(".yml") }); + let romkan = get_list("romkan", { |f| f.to_string_lossy().ends_with(".yml") }); info!("romkan: {:?}", romkan); for item in romkan { cbt.append(Some(&item.path), &item.name); } + cbt.set_active_id(Some(&config.lock().unwrap().romkan)); + + let config = config.clone(); + cbt.connect_changed(move |f| { + if let Some(id) = f.active_id() { + config.lock().unwrap().romkan = id.to_string(); + } + }); + cbt }, 1, @@ -153,13 +214,21 @@ fn build_core_pane() -> Grid { grid.attach( &{ let cbt = ComboBoxText::new(); - let romkan = get_keymap_list("model", { + let model = get_list("model", { |f| !f.file_name().unwrap().to_string_lossy().starts_with('.') }); - info!("model: {:?}", romkan); - for item in romkan { + info!("model: {:?}", model); + for item in model { cbt.append(Some(&item.path), &item.name); } + cbt.set_active_id(Some(&config.lock().unwrap().model)); + + cbt.connect_changed(move |f| { + if let Some(id) = f.active_id() { + config.lock().unwrap().model = id.to_string(); + } + }); + cbt }, 1, @@ -167,11 +236,59 @@ fn build_core_pane() -> Grid { 1, 1, ); - grid + Ok(grid) } -fn build_dict_pane() -> Label { - Label::new(Some("(工事中)")) +fn build_dict_pane(config: Arc>) -> Grid { + let grid = Grid::builder().column_spacing(10).build(); + // TODO /usr/share/skk/ 以下のものを拾ってきて入れる + for (i, dict_config) in config.lock().unwrap().dicts.iter().enumerate() { + grid.attach( + &Label::builder() + .xalign(0_f32) + .label(dict_config.path.as_str()) + .build(), + 0, + i as i32, + 1, + 1, + ); + + let cbt = ComboBoxText::builder().build(); + for usage in vec![ + DictUsage::Normal, + DictUsage::SingleTerm, + DictUsage::Disabled, + ] { + cbt.append(Some(usage.as_str()), usage.text_jp()); + } + cbt.set_active_id(Some(dict_config.usage.as_str())); + { + let config = config.clone(); + let path = dict_config.path.clone(); + cbt.connect_changed(move |f| { + if let Some(id) = f.active_id() { + let mut config = config.lock().unwrap(); + for mut dict in &mut config.dicts { + if dict.path == path { + dict.usage = DictUsage::from(&id).unwrap(); + break; + } + } + } + }); + } + grid.attach(&cbt, 1, i as i32, 1, 1); + + grid.attach( + &Label::new(Some(dict_config.dict_type.as_str())), + 2, + i as i32, + 1, + 1, + ); + } + grid } fn build_about_pane() -> Label { diff --git a/akaza-data/src/subcmd/check.rs b/akaza-data/src/subcmd/check.rs index 4ec82d5..8924fae 100644 --- a/akaza-data/src/subcmd/check.rs +++ b/akaza-data/src/subcmd/check.rs @@ -4,7 +4,7 @@ use std::sync::{Arc, Mutex}; use log::info; -use libakaza::config::{Config, DictConfig, DictEncoding, DictType}; +use libakaza::config::{Config, DictConfig, DictEncoding, DictType, DictUsage}; use libakaza::engine::bigram_word_viterbi_engine::BigramWordViterbiEngineBuilder; use libakaza::user_side_data::user_data::UserData; @@ -16,14 +16,15 @@ pub fn check(yomi: &str, expected: Option, user_data: bool) -> anyhow::R dict_type: DictType::SKK, encoding: DictEncoding::EucJp, path: "/usr/share/skk/SKK-JISYO.L".to_string(), + usage: DictUsage::Normal, }, DictConfig { dict_type: DictType::SKK, encoding: DictEncoding::Utf8, path: "data/SKK-JISYO.akaza".to_string(), + usage: DictUsage::Normal, }, ], - single_term: Default::default(), romkan: Default::default(), keymap: Default::default(), model: Default::default(), diff --git a/akaza-data/src/subcmd/evaluate.rs b/akaza-data/src/subcmd/evaluate.rs index f0418b4..879f2ff 100644 --- a/akaza-data/src/subcmd/evaluate.rs +++ b/akaza-data/src/subcmd/evaluate.rs @@ -5,7 +5,7 @@ use std::time::SystemTime; use anyhow::Context; use log::info; -use libakaza::config::{Config, DictConfig, DictEncoding, DictType}; +use libakaza::config::{Config, DictConfig, DictEncoding, DictType, DictUsage}; use libakaza::engine::base::HenkanEngine; use libakaza::engine::bigram_word_viterbi_engine::BigramWordViterbiEngineBuilder; @@ -58,6 +58,7 @@ pub fn evaluate( dict_type: DictType::SKK, encoding: DictEncoding::EucJp, path: path.clone(), + usage: DictUsage::Normal, }) } @@ -66,12 +67,12 @@ pub fn evaluate( dict_type: DictType::SKK, encoding: DictEncoding::Utf8, path: path.clone(), + usage: DictUsage::Normal, }) } let mut builder = BigramWordViterbiEngineBuilder::new(Config { dicts, - single_term: Default::default(), romkan: Default::default(), keymap: Default::default(), model: Default::default(), diff --git a/ibus-akaza/src/context.rs b/ibus-akaza/src/context.rs index 8754d8c..c621147 100644 --- a/ibus-akaza/src/context.rs +++ b/ibus-akaza/src/context.rs @@ -102,7 +102,10 @@ impl AkazaContext { ) { debug!("do_property_activate: {}, {}", prop_name, prop_state); if prop_name == "PrefPane" { - open_configuration_window(); + match open_configuration_window() { + Ok(_) => {} + Err(e) => info!("Err: {}", e), + } } else if prop_state == IBusPropState_PROP_STATE_CHECKED && prop_name.starts_with("InputMode.") { diff --git a/ibus-akaza/src/keymap.rs b/ibus-akaza/src/keymap.rs index c3259aa..1f04391 100644 --- a/ibus-akaza/src/keymap.rs +++ b/ibus-akaza/src/keymap.rs @@ -38,8 +38,8 @@ impl KeyMap { unsafe { ibus_keyval_from_name(cs.as_ptr()) } } - pub(crate) fn new(keymap_name: String) -> anyhow::Result { - let keymap = Keymap::load(keymap_name.as_str())?; + pub(crate) fn new(keymap_path: String) -> anyhow::Result { + let keymap = Keymap::load(keymap_path.as_str())?; let mut mapping: HashMap = HashMap::new(); for (key_pattern, command) in keymap { diff --git a/libakaza/src/config.rs b/libakaza/src/config.rs index 4713ead..07b1ad7 100644 --- a/libakaza/src/config.rs +++ b/libakaza/src/config.rs @@ -8,17 +8,21 @@ dicts: use std::fmt::Display; use std::fmt::Formatter; use std::fs::File; -use std::io::BufReader; +use std::io::{BufReader, Write}; +use std::path::PathBuf; -use anyhow::Result; +use anyhow::{bail, Result}; use log::{info, warn}; use serde::{Deserialize, Serialize}; + use DictEncoding::Utf8; +use crate::config::DictUsage::{Normal, SingleTerm}; +use crate::resource::detect_resource_path; + #[derive(Debug, PartialEq, Serialize, Deserialize, Default)] pub struct Config { pub dicts: Vec, - pub single_term: Vec, /// ローマ字かな変換テーブルの指定 /// "default", "kana", etc. @@ -37,15 +41,15 @@ pub struct Config { } fn default_romkan() -> String { - "default".to_string() + detect_resource_path("romkan", "default").unwrap() } fn default_keymap() -> String { - "default".to_string() + detect_resource_path("keymap", "default").unwrap() } fn default_model() -> String { - "default".to_string() + detect_resource_path("model", "default").unwrap() } impl Config { @@ -56,9 +60,22 @@ impl Config { Ok(config) } - pub fn load() -> Result { + pub fn file_name() -> Result { let basedir = xdg::BaseDirectories::with_prefix("akaza")?; - let configfile = basedir.get_config_file("config.yml"); + Ok(basedir.get_config_file("config.yml")) + } + + pub fn save(&self) -> Result<()> { + let file_name = Self::file_name()?; + let yml = serde_yaml::to_string(self)?; + info!("Write to file: {}", file_name.to_str().unwrap()); + let mut fp = File::create(file_name)?; + fp.write_all(yml.as_bytes())?; + Ok(()) + } + + pub fn load() -> Result { + let configfile = Self::file_name()?; let config = match Config::load_from_file(configfile.to_str().unwrap()) { Ok(config) => config, Err(err) => { @@ -85,11 +102,11 @@ pub struct DictConfig { /// Encoding of the dictionary /// Default: UTF-8 - // #[serde(default = "default_encoding")] pub encoding: DictEncoding, - // #[serde(default = "default_dict_type")] pub dict_type: DictType, + + pub usage: DictUsage, } fn default_encoding() -> DictEncoding { @@ -121,7 +138,7 @@ impl Display for DictEncoding { impl DictEncoding { pub fn as_str(&self) -> &'static str { match self { - DictEncoding::Utf8 => "UTF-8", + Utf8 => "UTF-8", DictEncoding::EucJp => "EUC-JP", } } @@ -152,6 +169,46 @@ impl DictType { } } +#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)] +pub enum DictUsage { + Normal, + SingleTerm, + Disabled, +} + +impl Default for DictUsage { + fn default() -> Self { + Normal + } +} + +impl DictUsage { + pub fn from(s: &str) -> Result { + match s { + "Normal" => Ok(Normal), + "SingleTerm" => Ok(SingleTerm), + "Disabled" => Ok(DictUsage::Disabled), + _ => bail!("Unknown name: {:?}", s), + } + } + + pub fn as_str(&self) -> &'static str { + match self { + Normal => "Normal", + SingleTerm => "SingleTerm", + DictUsage::Disabled => "Disabled", + } + } + + pub fn text_jp(&self) -> &'static str { + match self { + Normal => "通常辞書", + SingleTerm => "単項", + DictUsage::Disabled => "無効", + } + } +} + #[cfg(test)] mod tests { use super::*; @@ -166,6 +223,7 @@ mod tests { path: "/usr/share/skk/SKK-JISYO.L".to_string(), encoding: DictEncoding::EucJp, dict_type: DictType::SKK, + usage: DictUsage::Normal, } ); Ok(()) diff --git a/libakaza/src/engine/bigram_word_viterbi_engine.rs b/libakaza/src/engine/bigram_word_viterbi_engine.rs index 058d930..caee778 100644 --- a/libakaza/src/engine/bigram_word_viterbi_engine.rs +++ b/libakaza/src/engine/bigram_word_viterbi_engine.rs @@ -4,7 +4,7 @@ use std::sync::{Arc, Mutex}; use anyhow::Result; -use crate::config::{Config, DictConfig, DictEncoding, DictType}; +use crate::config::{Config, DictConfig, DictEncoding, DictType, DictUsage}; use crate::dict::loader::load_dicts_ex; use crate::engine::base::HenkanEngine; use crate::graph::candidate::Candidate; @@ -124,21 +124,22 @@ impl BigramWordViterbiEngineBuilder { let system_unigram_lm = match &self.model_dir { Some(path) => MarisaSystemUnigramLM::load(&format!("{}/unigram.model", path)), - None => MarisaSystemUnigramLM::load( - Self::try_load(&format!("{}/unigram.model", model_name))?.as_str(), - ), + None => { + MarisaSystemUnigramLM::load(Self::try_load(&model_name, "unigram.model")?.as_str()) + } }?; let system_bigram_lm = match &self.model_dir { Some(path) => MarisaSystemBigramLM::load(&format!("{}/bigram.model", path.clone())), - None => MarisaSystemBigramLM::load( - Self::try_load(&format!("{}/bigram.model", model_name))?.as_str(), - ), + None => { + MarisaSystemBigramLM::load(Self::try_load(&model_name, "bigram.model")?.as_str()) + } }?; + // TODO Merge self.model_dir and config.model let system_dict = match &self.model_dir { Some(path) => { format!("{}/SKK-JISYO.akaza", path) } - None => Self::try_load(&format!("{}/SKK-JISYO.akaza", model_name))?, + None => Self::try_load(&model_name, "SKK-JISYO.akaza")?, }; let user_data = if let Some(d) = &self.user_data { @@ -148,17 +149,33 @@ impl BigramWordViterbiEngineBuilder { }; let dict = { - let mut dicts = self.config.dicts.to_vec(); + let mut dicts = self + .config + .dicts + .iter() + .filter(|it| it.usage == DictUsage::Normal) + .cloned() + .collect::>(); dicts.push(DictConfig { path: system_dict, dict_type: DictType::SKK, encoding: DictEncoding::Utf8, + usage: DictUsage::Normal, }); load_dicts_ex(&dicts, "kana_kanji_cache.marisa")? }; - let single_term = load_dicts_ex(&self.config.single_term, "single_term_cache.marisa")?; + let single_term = load_dicts_ex( + &self + .config + .dicts + .iter() + .filter(|it| it.usage == DictUsage::SingleTerm) + .cloned() + .collect::>(), + "single_term_cache.marisa", + )?; // 辞書を元に、トライを作成していく。 let mut kana_trie = CedarwoodKanaTrie::default(); @@ -203,7 +220,7 @@ impl BigramWordViterbiEngineBuilder { }) } - fn try_load(name: &str) -> Result { - detect_resource_path("model", name) + fn try_load(model_dir: &str, name: &str) -> Result { + Ok(model_dir.to_string() + "/" + name) } } diff --git a/libakaza/src/keymap.rs b/libakaza/src/keymap.rs index 918f198..ef2d156 100644 --- a/libakaza/src/keymap.rs +++ b/libakaza/src/keymap.rs @@ -92,11 +92,10 @@ pub enum KeyState { } impl Keymap { - pub fn load(name: &str) -> Result> { - let pathstr = detect_resource_path("keymap", &format!("{}.yml", name))?; - info!("Load {}", pathstr); + pub fn load(keymap_path: &str) -> Result> { + info!("Load {}", keymap_path); let got: Keymap = serde_yaml::from_reader(BufReader::new( - File::open(&pathstr).with_context(|| pathstr)?, + File::open(keymap_path).with_context(|| keymap_path.to_string())?, ))?; if let Some(parent) = &got.extends { diff --git a/libakaza/src/resource.rs b/libakaza/src/resource.rs index b1433a9..fbea4e6 100644 --- a/libakaza/src/resource.rs +++ b/libakaza/src/resource.rs @@ -11,10 +11,12 @@ pub fn detect_resource_path(base: &str, name: &str) -> anyhow::Result { .with_context(|| "Opening xdg directory with 'akaza' prefix")?; let pathbuf = basedirs.find_data_file(&target_path); let Some(pathbuf) = pathbuf else { - bail!("Cannot find {:?} in XDG_DATA_HOME or XDG_DATA_DIRS(XDG_DATA_HOME={:?}, XDG_DATA_DIRS={:?})", + bail!("Cannot find {:?} in XDG_DATA_HOME or XDG_DATA_DIRS(XDG_DATA_HOME={:?}, XDG_DATA_DIRS={:?}, base={:?}, name={:?})", target_path, basedirs.get_data_home().to_string_lossy().to_string(), basedirs.get_data_dirs().iter().map(|x| x.to_string_lossy().to_string()).collect::>(), + base, + name ) }; pathbuf.to_string_lossy().to_string() diff --git a/libakaza/src/romkan.rs b/libakaza/src/romkan.rs index 5898a0c..8e240cb 100644 --- a/libakaza/src/romkan.rs +++ b/libakaza/src/romkan.rs @@ -14,11 +14,10 @@ pub struct RomKanConfig { extends: Option, } -fn load_romkan_map(name: &str) -> anyhow::Result> { - let pathstr = resource::detect_resource_path("romkan", &format!("{}.yml", name))?; - info!("Load {}", pathstr); +fn load_romkan_map(file_path: &str) -> anyhow::Result> { + info!("Load {}", file_path); let got: RomKanConfig = serde_yaml::from_reader(BufReader::new( - File::open(&pathstr).with_context(|| pathstr)?, + File::open(file_path).with_context(|| file_path.to_string())?, ))?; if let Some(parent) = got.extends {