diff --git a/Cargo.lock b/Cargo.lock index 604f5412..0870a135 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -66,9 +66,9 @@ checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" [[package]] name = "cc" -version = "1.2.47" +version = "1.2.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd405d82c84ff7f35739f175f67d8b9fb7687a0e84ccdc78bd3568839827cf07" +checksum = "c481bdbf0ed3b892f6f806287d72acd515b352a4ec27a208489b8c1bc839633a" dependencies = [ "find-msvc-tools", "shlex", @@ -85,9 +85,9 @@ name = "chewing" version = "0.11.0-alpha.6" dependencies = [ "der", - "log", "rusqlite", "tempfile", + "tracing", ] [[package]] @@ -105,9 +105,9 @@ name = "chewing_capi" version = "0.11.0-alpha.6" dependencies = [ "chewing", - "env_logger", - "log", "tempfile", + "tracing", + "tracing-subscriber", ] [[package]] @@ -182,25 +182,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "env_filter" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" -dependencies = [ - "log", -] - -[[package]] -name = "env_logger" -version = "0.11.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" -dependencies = [ - "env_filter", - "log", -] - [[package]] name = "errno" version = "0.3.14" @@ -247,8 +228,8 @@ version = "0.0.0" dependencies = [ "chewing", "chewing_capi", - "env_logger", - "log", + "tracing", + "tracing-subscriber", ] [[package]] @@ -293,11 +274,17 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" -version = "0.2.177" +version = "0.2.178" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" +checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" [[package]] name = "libsqlite3-sys" @@ -318,9 +305,18 @@ checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" [[package]] name = "log" -version = "0.4.28" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "nu-ansi-term" +version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys", +] [[package]] name = "once_cell" @@ -334,6 +330,12 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + [[package]] name = "pkg-config" version = "0.3.32" @@ -397,6 +399,15 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + [[package]] name = "shlex" version = "1.3.0" @@ -439,6 +450,47 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "tracing" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d15d90a0b5c19378952d479dc858407149d7bb45a14de0142f6c534b16fc647" +dependencies = [ + "log", + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a04e24fab5c89c6a36eb8558c9656f30d81de51dfa4d3b45f26b21d61fa0a6c" +dependencies = [ + "once_cell", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" +dependencies = [ + "nu-ansi-term", + "sharded-slab", + "thread_local", + "tracing-core", +] + [[package]] name = "unicode-ident" version = "1.0.22" diff --git a/Cargo.toml b/Cargo.toml index 90dd824e..fccb102b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,8 +19,8 @@ include = [ [dependencies] der = { version = "0.7.7", features = ["std"] } -log = { workspace = true } rusqlite = { version = ">= 0.28.0", optional = true } +tracing = { workspace = true } [dev-dependencies] tempfile = { workspace = true } @@ -29,15 +29,25 @@ tempfile = { workspace = true } default = [] sqlite = ["dep:rusqlite"] sqlite-bundled = ["sqlite", "rusqlite/bundled"] +log = ["tracing/log"] [workspace] members = ["capi", "fuzzer", "tests/testhelper", "tools"] resolver = "3" [workspace.dependencies] -log = "0.4.21" tempfile = "3.10.1" +[workspace.dependencies.tracing] +version = "0.1.18" +default-features = false +features = ["std", "release_max_level_info"] + +[workspace.dependencies.tracing-subscriber] +version = "0.3.0" +default-features = false +features = ["ansi", "fmt", "std"] + [profile.release] lto = true opt-level = 3 diff --git a/NEWS b/NEWS index 62b56ad0..b1c6d026 100644 --- a/NEWS +++ b/NEWS @@ -38,6 +38,7 @@ What's New in libchewing (unreleased) - autolearn: new phrases with break words inside will be learned both with and without the break word. - rust: simplified dictionary API. + - rust: logging now depends on tracing and tracing-subscriber. * Dictionary - Default symbols.dat now includes commonly used emojis. diff --git a/capi/Cargo.toml b/capi/Cargo.toml index 8c714e1f..e101d17f 100644 --- a/capi/Cargo.toml +++ b/capi/Cargo.toml @@ -11,8 +11,8 @@ crate-type = ["rlib", "staticlib"] [dependencies] chewing = { version = "0.11.0-alpha.6", path = ".." } -env_logger = { version = ">= 0.11.0-alpha.6", default-features = false } -log = { workspace = true } +tracing = { workspace = true } +tracing-subscriber = { workspace = true } [dev-dependencies] tempfile = { workspace = true } diff --git a/capi/src/io.rs b/capi/src/io.rs index 7a43b23f..c1ae3f65 100644 --- a/capi/src/io.rs +++ b/capi/src/io.rs @@ -1,11 +1,13 @@ use std::{ cmp::min, collections::BTreeMap, + env, ffi::{CStr, CString, c_char, c_int, c_uint, c_ushort, c_void}, mem, ops::Not, ptr::{null, null_mut}, - slice, str, + slice, + str::{self, FromStr}, sync::RwLock, }; @@ -35,23 +37,23 @@ use chewing::{ }, zhuyin::Syllable, }; -use log::{debug, error, info}; - -use crate::public::{ - CHEWING_CONVERSION_ENGINE, CHINESE_MODE, ChewingConfigData, ChewingContext, FULLSHAPE_MODE, - FUZZY_CHEWING_CONVERSION_ENGINE, HALFSHAPE_MODE, IntervalType, MAX_SELKEY, - SIMPLE_CONVERSION_ENGINE, SYMBOL_MODE, SelKeys, +use tracing::{debug, error, info, level_filters::LevelFilter}; +use tracing_subscriber::{filter::Targets, layer::SubscriberExt, util::SubscriberInitExt}; + +use crate::{ + logger::init_scoped_logging_subscriber, + public::{ + CHEWING_CONVERSION_ENGINE, CHINESE_MODE, ChewingConfigData, ChewingContext, FULLSHAPE_MODE, + FUZZY_CHEWING_CONVERSION_ENGINE, HALFSHAPE_MODE, IntervalType, MAX_SELKEY, + SIMPLE_CONVERSION_ENGINE, SYMBOL_MODE, SelKeys, + }, }; -use super::logger::ChewingLogger; - const TRUE: c_int = 1; const FALSE: c_int = 0; const OK: c_int = 0; const ERROR: c_int = -1; -static LOGGER: ChewingLogger = ChewingLogger::new(); - enum Owned { CString, CUShortSlice(usize), @@ -166,15 +168,22 @@ pub unsafe extern "C" fn chewing_new3( syspath: *const c_char, userpath: *const c_char, enabled_dicts: *const c_char, - logger: Option, - loggerdata: *mut c_void, + logger_fn: Option< + unsafe extern "C" fn(data: *mut c_void, level: c_int, fmt: *const c_char, ...), + >, + logger_data: *mut c_void, ) -> *mut ChewingContext { - LOGGER.init(); - let _ = log::set_logger(&LOGGER); - log::set_max_level(log::LevelFilter::Trace); - if let Some(logger) = logger { - LOGGER.set(Some((logger, loggerdata))); - } + let targets = match env::var("RUST_LOG") { + Ok(var) => Targets::from_str(&var).unwrap_or_default(), + Err(_) => Targets::new(), + }; + let _ = tracing_subscriber::fmt() + .without_time() + .with_max_level(LevelFilter::TRACE) + .finish() + .with(targets) + .try_init(); + let _logger_guard = init_scoped_logging_subscriber(logger_fn, logger_data); let mut sys_loader = SystemDictionaryLoader::new(); let mut dict_names: Vec = DEFAULT_DICT_NAMES.iter().map(|&n| n.to_owned()).collect(); if !syspath.is_null() { @@ -266,6 +275,8 @@ pub unsafe extern "C" fn chewing_new3( cand_buf: [0; 256], aux_buf: [0; 256], kbtype_buf: [0; 32], + logger_fn, + logger_data, }); let ptr = Box::into_raw(context); info!("Initialized context {ptr:?}"); @@ -291,7 +302,6 @@ pub unsafe extern "C" fn chewing_get_defaultDictionaryNames() -> *const c_char { #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_delete(ctx: *mut ChewingContext) { if !ctx.is_null() { - LOGGER.set(None); info!("Destroying context {ctx:?}"); drop(unsafe { Box::from_raw(ctx) }) } @@ -365,6 +375,7 @@ macro_rules! as_ref_or_return { #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_Reset(ctx: *mut ChewingContext) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); ctx.editor.clear(); OK } @@ -385,6 +396,7 @@ pub unsafe extern "C" fn chewing_Reset(ctx: *mut ChewingContext) -> c_int { #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_ack(ctx: *mut ChewingContext) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); ctx.editor.ack(); OK } @@ -397,7 +409,8 @@ pub unsafe extern "C" fn chewing_config_has_option( ctx: *const ChewingContext, name: *const c_char, ) -> c_int { - let _ctx = as_ref_or_return!(ctx, ERROR); + let ctx = as_ref_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); let cstr = unsafe { CStr::from_ptr(name) }; let name = cstr.to_string_lossy(); @@ -433,6 +446,7 @@ pub unsafe extern "C" fn chewing_config_get_int( name: *const c_char, ) -> c_int { let ctx = as_ref_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); if unsafe { chewing_config_has_option(ctx, name) } != 1 { return ERROR; @@ -485,6 +499,7 @@ pub unsafe extern "C" fn chewing_config_set_int( value: c_int, ) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); if unsafe { chewing_config_has_option(ctx, name) } != 1 { return ERROR; @@ -613,6 +628,7 @@ pub unsafe extern "C" fn chewing_config_get_str( value: *mut *mut c_char, ) -> c_int { let ctx = as_ref_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); if unsafe { chewing_config_has_option(ctx, name) } != 1 { return ERROR; @@ -659,6 +675,7 @@ pub unsafe extern "C" fn chewing_config_set_str( value: *const c_char, ) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); if unsafe { chewing_config_has_option(ctx, name) } != 1 { return ERROR; @@ -731,6 +748,8 @@ pub unsafe extern "C" fn chewing_config_set_str( #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_set_KBType(ctx: *mut ChewingContext, kbtype: c_int) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); + use KeyboardLayoutCompat as KB; let kb_compat = match KB::try_from(kbtype as u8) { Ok(kb) => kb, @@ -775,6 +794,8 @@ pub unsafe extern "C" fn chewing_set_KBType(ctx: *mut ChewingContext, kbtype: c_ #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_get_KBType(ctx: *const ChewingContext) -> c_int { let ctx = as_ref_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); + ctx.kb_compat as c_int } @@ -799,6 +820,7 @@ pub unsafe extern "C" fn chewing_get_KBString(ctx: *const ChewingContext) -> *mu ctx, owned_into_raw(Owned::CString, CString::default().into_raw()) ); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); let kb_string = ctx.kb_compat.to_string(); owned_into_raw( @@ -964,6 +986,7 @@ pub unsafe extern "C" fn chewing_set_selKey( len: c_int, ) { let ctx = as_mut_or_return!(ctx); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); if sel_keys.is_null() || len != 10 { return; @@ -985,6 +1008,7 @@ pub unsafe extern "C" fn chewing_set_selKey( #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_get_selKey(ctx: *const ChewingContext) -> *mut c_int { let ctx = as_ref_or_return!(ctx, null_mut()); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); let len = ctx.sel_keys.0.len(); let ptr = Box::into_raw(ctx.sel_keys.0.to_vec().into_boxed_slice()); @@ -1188,6 +1212,7 @@ pub unsafe extern "C" fn chewing_get_autoLearn(ctx: *const ChewingContext) -> c_ #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_get_phoneSeq(ctx: *const ChewingContext) -> *mut c_ushort { let ctx = as_ref_or_return!(ctx, null_mut()); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); let syllables: Vec<_> = ctx .editor @@ -1212,6 +1237,7 @@ pub unsafe extern "C" fn chewing_get_phoneSeq(ctx: *const ChewingContext) -> *mu #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_get_phoneSeqLen(ctx: *const ChewingContext) -> c_int { let ctx = as_ref_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); ctx.editor .symbols() @@ -1255,17 +1281,14 @@ pub unsafe extern "C" fn chewing_get_phoneSeqLen(ctx: *const ChewingContext) -> #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_set_logger( ctx: *mut ChewingContext, - logger: Option, - user_data: *mut c_void, + logger_fn: Option< + unsafe extern "C" fn(data: *mut c_void, level: c_int, fmt: *const c_char, ...), + >, + logger_data: *mut c_void, ) { - as_mut_or_return!(ctx); - if let Some(logger) = logger { - log::set_max_level(log::LevelFilter::Trace); - LOGGER.set(Some((logger, user_data))); - } else { - log::set_max_level(log::LevelFilter::Off); - LOGGER.set(None); - } + let ctx = as_mut_or_return!(ctx); + ctx.logger_fn = logger_fn; + ctx.logger_data = logger_data; } /// Starts a userphrase enumeration. @@ -1300,6 +1323,7 @@ pub unsafe extern "C" fn chewing_set_logger( #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_userphrase_enumerate(ctx: *mut ChewingContext) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); ctx.userphrase_iter = Some(ctx.editor.user_dict().entries().peekable()); OK @@ -1321,6 +1345,7 @@ pub unsafe extern "C" fn chewing_userphrase_has_next( bopomofo_len: *mut c_uint, ) -> c_int { let ctx = as_mut_or_return!(ctx, FALSE); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); if ctx.userphrase_iter.is_none() { return 0; @@ -1371,6 +1396,7 @@ pub unsafe extern "C" fn chewing_userphrase_get( bopomofo_len: c_uint, ) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); if ctx.userphrase_iter.is_none() { return -1; @@ -1420,6 +1446,8 @@ pub unsafe extern "C" fn chewing_userphrase_add( bopomofo_buf: *const c_char, ) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); + let syllables = match unsafe { str_from_ptr_with_nul(bopomofo_buf) } { Some(bopomofo) => bopomofo .split_ascii_whitespace() @@ -1454,10 +1482,8 @@ pub unsafe extern "C" fn chewing_userphrase_remove( phrase_buf: *const c_char, bopomofo_buf: *const c_char, ) -> c_int { - let ctx = match unsafe { ctx.as_mut() } { - Some(ctx) => ctx, - None => return ERROR, - }; + let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); // return FALSE when phrase does not exist is C API only behavior if unsafe { chewing_userphrase_lookup(ctx, phrase_buf, bopomofo_buf) } != TRUE { @@ -1495,6 +1521,8 @@ pub unsafe extern "C" fn chewing_userphrase_lookup( bopomofo_buf: *const c_char, ) -> c_int { let ctx = as_mut_or_return!(ctx, FALSE); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); + let syllables = match unsafe { str_from_ptr_with_nul(bopomofo_buf) } { Some(bopomofo) => bopomofo .split_ascii_whitespace() @@ -1534,6 +1562,7 @@ pub unsafe extern "C" fn chewing_userphrase_lookup( #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_cand_list_first(ctx: *mut ChewingContext) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); if !ctx.editor.is_selecting() { return -1; @@ -1558,6 +1587,7 @@ pub unsafe extern "C" fn chewing_cand_list_first(ctx: *mut ChewingContext) -> c_ #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_cand_list_last(ctx: *mut ChewingContext) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); if !ctx.editor.is_selecting() { return -1; @@ -1577,6 +1607,7 @@ pub unsafe extern "C" fn chewing_cand_list_last(ctx: *mut ChewingContext) -> c_i #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_cand_list_has_next(ctx: *mut ChewingContext) -> c_int { let ctx = as_ref_or_return!(ctx, FALSE); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); if !ctx.editor.is_selecting() { return 0; @@ -1595,6 +1626,7 @@ pub unsafe extern "C" fn chewing_cand_list_has_next(ctx: *mut ChewingContext) -> #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_cand_list_has_prev(ctx: *mut ChewingContext) -> c_int { let ctx = as_ref_or_return!(ctx, FALSE); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); if !ctx.editor.is_selecting() { return 0; @@ -1618,6 +1650,8 @@ pub unsafe extern "C" fn chewing_cand_list_has_prev(ctx: *mut ChewingContext) -> #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_cand_list_next(ctx: *mut ChewingContext) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); + if !ctx.editor.is_selecting() { return -1; } @@ -1642,6 +1676,8 @@ pub unsafe extern "C" fn chewing_cand_list_next(ctx: *mut ChewingContext) -> c_i #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_cand_list_prev(ctx: *mut ChewingContext) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); + if !ctx.editor.is_selecting() { return -1; } @@ -1665,6 +1701,7 @@ pub unsafe extern "C" fn chewing_cand_list_prev(ctx: *mut ChewingContext) -> c_i #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_commit_preedit_buf(ctx: *mut ChewingContext) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); if ctx.editor.is_selecting() { return ERROR; @@ -1690,6 +1727,7 @@ pub unsafe extern "C" fn chewing_commit_preedit_buf(ctx: *mut ChewingContext) -> #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_clean_preedit_buf(ctx: *mut ChewingContext) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); if ctx.editor.is_selecting() { return ERROR; @@ -1713,6 +1751,7 @@ pub unsafe extern "C" fn chewing_clean_preedit_buf(ctx: *mut ChewingContext) -> #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_clean_bopomofo_buf(ctx: *mut ChewingContext) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); ctx.editor.clear_syllable_editor(); OK @@ -1790,6 +1829,7 @@ pub unsafe extern "C" fn chewing_handle_KeyboardEvent( state: u32, ) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); // XXX hack for selkey let key = if ctx.editor.is_selecting() { @@ -1845,6 +1885,7 @@ pub unsafe extern "C" fn chewing_handle_KeyboardEvent( #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_handle_Space(ctx: *mut ChewingContext) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); ctx.editor.process_keyevent(KeyboardEvent { code: KEY_SPACE, @@ -1862,6 +1903,7 @@ pub unsafe extern "C" fn chewing_handle_Space(ctx: *mut ChewingContext) -> c_int #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_handle_Esc(ctx: *mut ChewingContext) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); ctx.editor.process_keyevent(KeyboardEvent { code: KEY_ESC, @@ -1879,6 +1921,7 @@ pub unsafe extern "C" fn chewing_handle_Esc(ctx: *mut ChewingContext) -> c_int { #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_handle_Enter(ctx: *mut ChewingContext) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); ctx.editor.process_keyevent(KeyboardEvent { code: KEY_ENTER, @@ -1896,6 +1939,7 @@ pub unsafe extern "C" fn chewing_handle_Enter(ctx: *mut ChewingContext) -> c_int #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_handle_Del(ctx: *mut ChewingContext) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); ctx.editor.process_keyevent(KeyboardEvent { code: KEY_DELETE, @@ -1913,6 +1957,7 @@ pub unsafe extern "C" fn chewing_handle_Del(ctx: *mut ChewingContext) -> c_int { #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_handle_Backspace(ctx: *mut ChewingContext) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); ctx.editor.process_keyevent(KeyboardEvent { code: KEY_BACKSPACE, @@ -1930,6 +1975,7 @@ pub unsafe extern "C" fn chewing_handle_Backspace(ctx: *mut ChewingContext) -> c #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_handle_Tab(ctx: *mut ChewingContext) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); ctx.editor.process_keyevent(KeyboardEvent { code: KEY_TAB, @@ -1947,6 +1993,7 @@ pub unsafe extern "C" fn chewing_handle_Tab(ctx: *mut ChewingContext) -> c_int { #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_handle_ShiftLeft(ctx: *mut ChewingContext) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); ctx.editor.process_keyevent( KeyboardEvent::builder() @@ -1966,6 +2013,7 @@ pub unsafe extern "C" fn chewing_handle_ShiftLeft(ctx: *mut ChewingContext) -> c #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_handle_Left(ctx: *mut ChewingContext) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); ctx.editor.process_keyevent(KeyboardEvent { code: KEY_LEFT, @@ -1983,6 +2031,7 @@ pub unsafe extern "C" fn chewing_handle_Left(ctx: *mut ChewingContext) -> c_int #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_handle_ShiftRight(ctx: *mut ChewingContext) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); ctx.editor.process_keyevent( KeyboardEvent::builder() @@ -2002,6 +2051,7 @@ pub unsafe extern "C" fn chewing_handle_ShiftRight(ctx: *mut ChewingContext) -> #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_handle_Right(ctx: *mut ChewingContext) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); ctx.editor.process_keyevent(KeyboardEvent { code: KEY_RIGHT, @@ -2022,6 +2072,7 @@ pub unsafe extern "C" fn chewing_handle_Right(ctx: *mut ChewingContext) -> c_int #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_handle_Up(ctx: *mut ChewingContext) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); ctx.editor.process_keyevent(KeyboardEvent { code: KEY_UP, @@ -2039,6 +2090,7 @@ pub unsafe extern "C" fn chewing_handle_Up(ctx: *mut ChewingContext) -> c_int { #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_handle_Home(ctx: *mut ChewingContext) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); ctx.editor.process_keyevent(KeyboardEvent { code: KEY_HOME, @@ -2056,6 +2108,7 @@ pub unsafe extern "C" fn chewing_handle_Home(ctx: *mut ChewingContext) -> c_int #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_handle_End(ctx: *mut ChewingContext) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); ctx.editor.process_keyevent(KeyboardEvent { code: KEY_END, @@ -2073,6 +2126,7 @@ pub unsafe extern "C" fn chewing_handle_End(ctx: *mut ChewingContext) -> c_int { #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_handle_PageUp(ctx: *mut ChewingContext) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); ctx.editor.process_keyevent(KeyboardEvent { code: KEY_PAGEUP, @@ -2090,6 +2144,7 @@ pub unsafe extern "C" fn chewing_handle_PageUp(ctx: *mut ChewingContext) -> c_in #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_handle_PageDown(ctx: *mut ChewingContext) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); ctx.editor.process_keyevent(KeyboardEvent { code: KEY_PAGEDOWN, @@ -2109,6 +2164,7 @@ pub unsafe extern "C" fn chewing_handle_PageDown(ctx: *mut ChewingContext) -> c_ #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_handle_Down(ctx: *mut ChewingContext) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); ctx.editor.process_keyevent(KeyboardEvent { code: KEY_DOWN, @@ -2126,6 +2182,7 @@ pub unsafe extern "C" fn chewing_handle_Down(ctx: *mut ChewingContext) -> c_int #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_handle_Capslock(ctx: *mut ChewingContext) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); ctx.editor.process_keyevent( KeyboardEvent::builder() @@ -2147,6 +2204,7 @@ pub unsafe extern "C" fn chewing_handle_Capslock(ctx: *mut ChewingContext) -> c_ #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_handle_Default(ctx: *mut ChewingContext, key: c_int) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); let evt = map_ascii(&ctx.keymap, key as u8); @@ -2164,6 +2222,7 @@ pub unsafe extern "C" fn chewing_handle_Default(ctx: *mut ChewingContext, key: c #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_handle_CtrlNum(ctx: *mut ChewingContext, key: c_int) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); let (code, ksym) = match key as u8 { b'0' => (KEY_0, SYM_0), @@ -2197,6 +2256,7 @@ pub unsafe extern "C" fn chewing_handle_CtrlNum(ctx: *mut ChewingContext, key: c #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_handle_ShiftSpace(ctx: *mut ChewingContext) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); ctx.editor.process_keyevent( KeyboardEvent::builder() @@ -2215,7 +2275,8 @@ pub unsafe extern "C" fn chewing_handle_ShiftSpace(ctx: *mut ChewingContext) -> /// This function should be called with valid pointers. #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_handle_DblTab(ctx: *mut ChewingContext) -> c_int { - let _ctx = as_mut_or_return!(ctx, ERROR); + let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); // todo!() OK @@ -2232,6 +2293,7 @@ pub unsafe extern "C" fn chewing_handle_DblTab(ctx: *mut ChewingContext) -> c_in #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_handle_Numlock(ctx: *mut ChewingContext, key: c_int) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); let (code, ksym) = match key as u8 { b'0' => (KEY_KP0, SYM_KP0), @@ -2272,6 +2334,7 @@ pub unsafe extern "C" fn chewing_handle_Numlock(ctx: *mut ChewingContext, key: c #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_commit_Check(ctx: *const ChewingContext) -> c_int { let ctx = as_ref_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); !ctx.editor.display_commit().is_empty() as c_int } @@ -2295,6 +2358,7 @@ pub unsafe extern "C" fn chewing_commit_String(ctx: *const ChewingContext) -> *m ctx, owned_into_raw(Owned::CString, CString::default().into_raw()) ); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); let buffer = ctx.editor.display_commit(); let cstr = match CString::new(buffer) { @@ -2316,6 +2380,7 @@ pub unsafe extern "C" fn chewing_commit_String(ctx: *const ChewingContext) -> *m #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_commit_String_static(ctx: *const ChewingContext) -> *const c_char { let ctx = as_mut_or_return!(ctx.cast_mut(), global_empty_cstr()); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); copy_cstr(&mut ctx.commit_buf, ctx.editor.display_commit()) } @@ -2339,6 +2404,7 @@ pub unsafe extern "C" fn chewing_buffer_String(ctx: *const ChewingContext) -> *m ctx, owned_into_raw(Owned::CString, CString::default().into_raw()) ); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); let buffer = ctx.editor.display(); let cstr = match CString::new(buffer) { @@ -2360,6 +2426,7 @@ pub unsafe extern "C" fn chewing_buffer_String(ctx: *const ChewingContext) -> *m #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_buffer_String_static(ctx: *const ChewingContext) -> *const c_char { let ctx = as_mut_or_return!(ctx.cast_mut(), global_empty_cstr()); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); copy_cstr(&mut ctx.preedit_buf, &ctx.editor.display()) } @@ -2374,6 +2441,7 @@ pub unsafe extern "C" fn chewing_buffer_String_static(ctx: *const ChewingContext #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_buffer_Check(ctx: *const ChewingContext) -> c_int { let ctx = as_ref_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); !ctx.editor.is_empty() as c_int } @@ -2391,6 +2459,7 @@ pub unsafe extern "C" fn chewing_buffer_Check(ctx: *const ChewingContext) -> c_i #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_buffer_Len(ctx: *const ChewingContext) -> c_int { let ctx = as_ref_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); ctx.editor.len() as c_int } @@ -2409,6 +2478,7 @@ pub unsafe extern "C" fn chewing_bopomofo_String_static( ctx: *const ChewingContext, ) -> *const c_char { let ctx = as_mut_or_return!(ctx.cast_mut(), global_empty_cstr()); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); copy_cstr(&mut ctx.bopomofo_buf, &ctx.editor.syllable_buffer_display()) } @@ -2432,6 +2502,7 @@ pub unsafe extern "C" fn chewing_bopomofo_String(ctx: *const ChewingContext) -> ctx, owned_into_raw(Owned::CString, CString::default().into_raw()) ); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); let buffer = ctx.editor.syllable_buffer_display(); let cstr = match CString::new(buffer) { @@ -2451,6 +2522,7 @@ pub unsafe extern "C" fn chewing_bopomofo_String(ctx: *const ChewingContext) -> #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_bopomofo_Check(ctx: *const ChewingContext) -> c_int { let ctx = as_ref_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); ctx.editor.entering_syllable() as c_int } @@ -2463,6 +2535,7 @@ pub unsafe extern "C" fn chewing_bopomofo_Check(ctx: *const ChewingContext) -> c #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_cursor_Current(ctx: *const ChewingContext) -> c_int { let ctx = as_ref_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); ctx.editor.cursor() as c_int } @@ -2480,6 +2553,7 @@ pub unsafe extern "C" fn chewing_cursor_Current(ctx: *const ChewingContext) -> c #[deprecated(note = "The chewing_cand_TotalPage function could achieve the same effect.")] pub unsafe extern "C" fn chewing_cand_CheckDone(ctx: *const ChewingContext) -> c_int { let ctx = as_ref_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); if ctx.editor.is_selecting() { FALSE @@ -2500,6 +2574,7 @@ pub unsafe extern "C" fn chewing_cand_CheckDone(ctx: *const ChewingContext) -> c #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_cand_TotalPage(ctx: *const ChewingContext) -> c_int { let ctx = as_ref_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); ctx.editor.total_page().unwrap_or_default() as c_int } @@ -2514,6 +2589,7 @@ pub unsafe extern "C" fn chewing_cand_TotalPage(ctx: *const ChewingContext) -> c #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_cand_ChoicePerPage(ctx: *const ChewingContext) -> c_int { let ctx = as_ref_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); ctx.editor.editor_options().candidates_per_page as c_int } @@ -2526,6 +2602,7 @@ pub unsafe extern "C" fn chewing_cand_ChoicePerPage(ctx: *const ChewingContext) #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_cand_TotalChoice(ctx: *const ChewingContext) -> c_int { let ctx = as_ref_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); match ctx.editor.all_candidates() { Ok(candidates) => candidates.len() as c_int, @@ -2551,6 +2628,7 @@ pub unsafe extern "C" fn chewing_cand_TotalChoice(ctx: *const ChewingContext) -> #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_cand_CurrentPage(ctx: *const ChewingContext) -> c_int { let ctx = as_ref_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); ctx.editor.current_page_no().unwrap_or_default() as c_int } @@ -2568,6 +2646,7 @@ pub unsafe extern "C" fn chewing_cand_CurrentPage(ctx: *const ChewingContext) -> #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_cand_Enumerate(ctx: *mut ChewingContext) { let ctx = as_mut_or_return!(ctx); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); if let Ok(candidates) = ctx.editor.paginated_candidates() { debug!("candidates: {candidates:?}"); @@ -2589,6 +2668,7 @@ pub unsafe extern "C" fn chewing_cand_Enumerate(ctx: *mut ChewingContext) { #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_cand_hasNext(ctx: *mut ChewingContext) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); if !ctx.editor.is_selecting() { return FALSE; @@ -2619,6 +2699,7 @@ pub unsafe extern "C" fn chewing_cand_String(ctx: *mut ChewingContext) -> *mut c ctx, owned_into_raw(Owned::CString, CString::default().into_raw()) ); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); match ctx.cand_iter.as_mut().and_then(|it| it.next()) { Some(phrase) => { @@ -2646,6 +2727,7 @@ pub unsafe extern "C" fn chewing_cand_String(ctx: *mut ChewingContext) -> *mut c #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_cand_String_static(ctx: *mut ChewingContext) -> *const c_char { let ctx = as_mut_or_return!(ctx, global_empty_cstr()); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); match ctx.cand_iter.as_mut().and_then(|it| it.next()) { Some(phrase) => copy_cstr(&mut ctx.cand_buf, &phrase), @@ -2677,6 +2759,7 @@ pub unsafe extern "C" fn chewing_cand_string_by_index( ctx, owned_into_raw(Owned::CString, CString::default().into_raw()) ); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); if let Ok(phrases) = ctx.editor.all_candidates() { if let Some(phrase) = phrases.get(index as usize) { @@ -2707,6 +2790,7 @@ pub unsafe extern "C" fn chewing_cand_string_by_index_static( index: c_int, ) -> *const c_char { let ctx = as_mut_or_return!(ctx, global_empty_cstr()); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); if let Ok(phrases) = ctx.editor.all_candidates() { if let Some(phrase) = phrases.get(index as usize) { @@ -2736,6 +2820,7 @@ pub unsafe extern "C" fn chewing_cand_choose_by_index( index: c_int, ) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); match ctx.editor.select(index as usize) { Ok(_) => OK, @@ -2755,6 +2840,7 @@ pub unsafe extern "C" fn chewing_cand_choose_by_index( #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_cand_open(ctx: *mut ChewingContext) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); match ctx.editor.start_selecting() { Ok(_) => OK, @@ -2772,6 +2858,7 @@ pub unsafe extern "C" fn chewing_cand_open(ctx: *mut ChewingContext) -> c_int { #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_cand_close(ctx: *mut ChewingContext) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); match ctx.editor.cancel_selecting() { Ok(_) => OK, @@ -2792,6 +2879,7 @@ pub unsafe extern "C" fn chewing_cand_close(ctx: *mut ChewingContext) -> c_int { #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_interval_Enumerate(ctx: *mut ChewingContext) { let ctx = as_mut_or_return!(ctx); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); ctx.interval_iter = Some( (Box::new(ctx.editor.intervals().filter(|it| it.is_phrase)) @@ -2810,6 +2898,7 @@ pub unsafe extern "C" fn chewing_interval_Enumerate(ctx: *mut ChewingContext) { #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_interval_hasNext(ctx: *mut ChewingContext) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); ctx.interval_iter .as_mut() @@ -2829,6 +2918,7 @@ pub unsafe extern "C" fn chewing_interval_hasNext(ctx: *mut ChewingContext) -> c #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_interval_Get(ctx: *mut ChewingContext, it: *mut IntervalType) { let ctx = as_mut_or_return!(ctx); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); let it = unsafe { match it.as_mut() { @@ -2854,6 +2944,7 @@ pub unsafe extern "C" fn chewing_interval_Get(ctx: *mut ChewingContext, it: *mut #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_aux_Check(ctx: *const ChewingContext) -> c_int { let ctx = as_ref_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); !ctx.editor.notification().is_empty() as c_int } @@ -2871,6 +2962,7 @@ pub unsafe extern "C" fn chewing_aux_Check(ctx: *const ChewingContext) -> c_int #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_aux_Length(ctx: *const ChewingContext) -> c_int { let ctx = as_ref_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); ctx.editor.notification().chars().count() as c_int } @@ -2894,6 +2986,7 @@ pub unsafe extern "C" fn chewing_aux_String(ctx: *const ChewingContext) -> *mut Some(ctx) => ctx, None => return owned_into_raw(Owned::CString, CString::default().into_raw()), }; + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); let cstring = CString::new(ctx.editor.notification()).expect("notification should be valid UTF-8"); @@ -2912,6 +3005,7 @@ pub unsafe extern "C" fn chewing_aux_String(ctx: *const ChewingContext) -> *mut #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_aux_String_static(ctx: *const ChewingContext) -> *const c_char { let ctx = as_mut_or_return!(ctx.cast_mut(), global_empty_cstr()); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); copy_cstr(&mut ctx.aux_buf, ctx.editor.notification()) } @@ -2926,6 +3020,7 @@ pub unsafe extern "C" fn chewing_aux_String_static(ctx: *const ChewingContext) - #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_keystroke_CheckIgnore(ctx: *const ChewingContext) -> c_int { let ctx = as_ref_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); match ctx.editor.last_key_behavior() { EditorKeyBehavior::Ignore => TRUE, @@ -2947,6 +3042,7 @@ pub unsafe extern "C" fn chewing_keystroke_CheckIgnore(ctx: *const ChewingContex #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_keystroke_CheckAbsorb(ctx: *const ChewingContext) -> c_int { let ctx = as_ref_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); match ctx.editor.last_key_behavior() { EditorKeyBehavior::Absorb => TRUE, @@ -2981,6 +3077,7 @@ pub unsafe extern "C" fn chewing_kbtype_Total(_ctx: *const ChewingContext) -> c_ #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_kbtype_Enumerate(ctx: *mut ChewingContext) { let ctx = as_mut_or_return!(ctx); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); ctx.kbcompat_iter = Some( (Box::new((0..).map_while(|id| KeyboardLayoutCompat::try_from(id).ok())) @@ -2999,6 +3096,7 @@ pub unsafe extern "C" fn chewing_kbtype_Enumerate(ctx: *mut ChewingContext) { #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_kbtype_hasNext(ctx: *mut ChewingContext) -> c_int { let ctx = as_mut_or_return!(ctx, ERROR); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); ctx.kbcompat_iter .as_mut() @@ -3027,6 +3125,7 @@ pub unsafe extern "C" fn chewing_kbtype_String(ctx: *mut ChewingContext) -> *mut ctx, owned_into_raw(Owned::CString, CString::default().into_raw()) ); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); match ctx.kbcompat_iter.as_mut().and_then(|it| it.next()) { Some(kb_compat) => { @@ -3054,6 +3153,7 @@ pub unsafe extern "C" fn chewing_kbtype_String(ctx: *mut ChewingContext) -> *mut #[unsafe(no_mangle)] pub unsafe extern "C" fn chewing_kbtype_String_static(ctx: *mut ChewingContext) -> *const c_char { let ctx = as_mut_or_return!(ctx, global_empty_cstr()); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); match ctx.kbcompat_iter.as_mut().and_then(|it| it.next()) { Some(kb_compat) => copy_cstr(&mut ctx.kbtype_buf, &kb_compat.to_string()), @@ -3107,6 +3207,7 @@ pub unsafe extern "C" fn chewing_zuin_String( ctx, owned_into_raw(Owned::CString, CString::default().into_raw()) ); + let _logger_guard = init_scoped_logging_subscriber(ctx.logger_fn, ctx.logger_data); let syllable = ctx.editor.syllable_buffer_display(); unsafe { diff --git a/capi/src/logger.rs b/capi/src/logger.rs index 6b973cd3..f9c9d244 100644 --- a/capi/src/logger.rs +++ b/capi/src/logger.rs @@ -1,97 +1,101 @@ use std::{ ffi::{CString, c_char, c_int, c_void}, - sync::{ - Mutex, - atomic::{AtomicPtr, Ordering::Relaxed}, - }, + io::Write, + mem, }; -use log::{Level, Log, Metadata, Record}; +use tracing::Level; +use tracing::dispatcher::DefaultGuard; +use tracing_subscriber::{fmt::MakeWriter, util::SubscriberInitExt}; -use super::setup::{ +use crate::setup::{ CHEWING_LOG_DEBUG, CHEWING_LOG_ERROR, CHEWING_LOG_INFO, CHEWING_LOG_VERBOSE, CHEWING_LOG_WARN, }; -type ExternLoggerFn = +pub(crate) type ExternLoggerFn = unsafe extern "C" fn(data: *mut c_void, level: c_int, fmt: *const c_char, arg: ...); +#[derive(Clone)] pub(crate) struct ChewingLogger { - env_logger: Mutex>, - logger: Mutex)>>, + level: c_int, + buffer: Vec, + logger_fn: ExternLoggerFn, + logger_data: *mut c_void, } impl ChewingLogger { - pub(crate) const fn new() -> ChewingLogger { + pub(crate) fn new(logger_fn: ExternLoggerFn, logger_data: *mut c_void) -> ChewingLogger { ChewingLogger { - env_logger: Mutex::new(None), - logger: Mutex::new(None), + level: 0, + buffer: vec![], + logger_fn, + logger_data, } } - pub(crate) fn init(&self) { - if let Ok(mut prev) = self.env_logger.lock() { - *prev = Some(env_logger::Logger::from_default_env()); - } +} + +unsafe impl Send for ChewingLogger {} +unsafe impl Sync for ChewingLogger {} + +impl<'a> MakeWriter<'a> for ChewingLogger { + type Writer = ChewingLogger; + fn make_writer(&'a self) -> Self::Writer { + self.clone() } - pub(crate) fn set(&self, logger: Option<(ExternLoggerFn, *mut c_void)>) { - if let Ok(mut prev) = self.logger.lock() { - *prev = logger.map(|(l, d)| (l, d.into())); - } + fn make_writer_for(&'a self, meta: &tracing::Metadata<'_>) -> Self::Writer { + let mut writer = self.make_writer(); + writer.level = as_chewing_level(meta.level()); + writer } } -impl Log for ChewingLogger { - fn enabled(&self, metadata: &Metadata<'_>) -> bool { - if let Ok(logger) = self.logger.lock() { - if logger.is_some() && metadata.level() <= Level::Debug { - return true; - } - } - if let Ok(logger) = self.env_logger.lock() { - if let Some(el) = logger.as_ref() { - return el.enabled(metadata); - } - } - false +impl Write for ChewingLogger { + fn write(&mut self, buf: &[u8]) -> std::io::Result { + self.buffer.write(buf) + } + fn flush(&mut self) -> std::io::Result<()> { + Ok(()) } +} - fn log(&self, record: &Record<'_>) { - if let Ok(logger) = self.logger.lock() { - if let Some((logger, logger_data)) = logger.as_ref() { - let fmt = format!( - "[{}:{} {}] {}", - record.file().unwrap_or("unknown"), - record.line().unwrap_or_default(), - record.module_path().unwrap_or("unknown"), - record.args() - ); - let fmt_cstring = CString::new(fmt).unwrap(); - unsafe { - logger( - logger_data.load(Relaxed), - as_chewing_level(record.level()), - c"%s\n".as_ptr().cast(), - fmt_cstring.as_ptr(), - ) - } - return; - } - } - if let Ok(logger) = self.env_logger.lock() { - if let Some(el) = logger.as_ref() { - el.log(record); +impl Drop for ChewingLogger { + fn drop(&mut self) { + if !self.buffer.is_empty() { + let buffer = mem::take(&mut self.buffer); + let fmt_cstring = CString::new(buffer).unwrap(); + unsafe { + (self.logger_fn)( + self.logger_data, + self.level, + c"%s".as_ptr().cast(), + fmt_cstring.as_ptr(), + ) } + return; } } - - fn flush(&self) {} } -fn as_chewing_level(level: Level) -> c_int { - (match level { - Level::Error => CHEWING_LOG_ERROR, - Level::Warn => CHEWING_LOG_WARN, - Level::Info => CHEWING_LOG_INFO, - Level::Debug => CHEWING_LOG_DEBUG, - Level::Trace => CHEWING_LOG_VERBOSE, +fn as_chewing_level(level: &Level) -> c_int { + (match *level { + Level::ERROR => CHEWING_LOG_ERROR, + Level::WARN => CHEWING_LOG_WARN, + Level::INFO => CHEWING_LOG_INFO, + Level::DEBUG => CHEWING_LOG_DEBUG, + Level::TRACE => CHEWING_LOG_VERBOSE, }) as c_int } + +pub(crate) fn init_scoped_logging_subscriber( + logger_fn: Option, + logger_data: *mut c_void, +) -> Option { + logger_fn.map(|logger_fn| { + tracing_subscriber::fmt() + .with_writer(ChewingLogger::new(logger_fn, logger_data)) + .without_time() + .with_ansi(false) + .finish() + .set_default() + }) +} diff --git a/capi/src/public.rs b/capi/src/public.rs index 5a0f6b38..3f454e0a 100644 --- a/capi/src/public.rs +++ b/capi/src/public.rs @@ -1,4 +1,8 @@ -use std::{ffi::c_int, fmt::Debug, iter::Peekable}; +use std::{ + ffi::{c_int, c_void}, + fmt::Debug, + iter::Peekable, +}; use chewing::{ conversion::Interval, @@ -7,6 +11,8 @@ use chewing::{ input::keymap::Keymap, }; +use crate::logger::ExternLoggerFn; + /// Indicates chewing will translate keystrokes to Chinese characters. pub const CHINESE_MODE: c_int = 1; /// Indicates the input mode is translating keystrokes to symbols. @@ -138,6 +144,8 @@ pub struct ChewingContext { pub(crate) cand_buf: [u8; 256], pub(crate) aux_buf: [u8; 256], pub(crate) kbtype_buf: [u8; 32], + pub(crate) logger_fn: Option, + pub(crate) logger_data: *mut c_void, } impl Debug for ChewingContext { @@ -151,6 +159,8 @@ impl Debug for ChewingContext { .field("interval_iter.is_some()", &self.interval_iter.is_some()) .field("userphrase_iter.is_some()", &self.userphrase_iter.is_some()) .field("sel_keys", &self.sel_keys) + .field("logger_fn", &self.logger_fn) + .field("logger_data", &self.logger_data) .finish_non_exhaustive() } } diff --git a/fuzzer/Cargo.toml b/fuzzer/Cargo.toml index 853c1bea..100f1408 100644 --- a/fuzzer/Cargo.toml +++ b/fuzzer/Cargo.toml @@ -8,5 +8,5 @@ edition = "2021" [dependencies] chewing = { version = "0.11.0-alpha.6", path = ".." } chewing_capi = { version = "0.11.0-alpha.6", path = "../capi" } -log = "0.4.21" -env_logger = { version = ">= 0.11.0-alpha.6", default-features = false } +tracing = { workspace = true } +tracing-subscriber = { workspace = true } diff --git a/fuzzer/src/bin/fuzzer.rs b/fuzzer/src/bin/fuzzer.rs index 45400f6a..de8905aa 100644 --- a/fuzzer/src/bin/fuzzer.rs +++ b/fuzzer/src/bin/fuzzer.rs @@ -96,7 +96,7 @@ impl From for ChewingHandle { } pub fn main() -> Result<()> { - env_logger::init(); + tracing_subscriber::fmt::init(); let syspath = env::args() .nth(1) diff --git a/fuzzer/src/bin/trieloader.rs b/fuzzer/src/bin/trieloader.rs index 232fbb57..d466cc73 100644 --- a/fuzzer/src/bin/trieloader.rs +++ b/fuzzer/src/bin/trieloader.rs @@ -5,10 +5,10 @@ use chewing::{ syl, zhuyin::Bopomofo, }; -use log::{debug, info}; +use tracing::{debug, info}; pub fn main() -> Result<()> { - env_logger::init(); + tracing_subscriber::fmt::init(); let dict_path = env::args() .nth(1) diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 00000000..bf96e774 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1 @@ +group_imports = "StdExternalCrate" diff --git a/src/conversion/chewing.rs b/src/conversion/chewing.rs index c254e0dc..e166a45f 100644 --- a/src/conversion/chewing.rs +++ b/src/conversion/chewing.rs @@ -3,16 +3,15 @@ use std::{ fmt::{Debug, Display, Write}, }; -use log::trace; +use tracing::trace; +use super::{Composition, ConversionEngine, Gap, Interval, Symbol}; use crate::{ conversion::Outcome, dictionary::{Dictionary, LookupStrategy, Phrase}, zhuyin::Syllable, }; -use super::{Composition, ConversionEngine, Gap, Interval, Symbol}; - /// The default Chewing conversion method. #[derive(Debug, Default)] pub struct ChewingEngine { @@ -517,6 +516,7 @@ impl Display for PossiblePath { mod tests { use std::collections::HashSet; + use super::ChewingEngine; use crate::{ conversion::{Composition, Gap, Interval, Outcome, Symbol, chewing::Edge}, dictionary::{Dictionary, TrieBuf}, @@ -524,8 +524,6 @@ mod tests { zhuyin::Bopomofo::*, }; - use super::ChewingEngine; - fn test_dictionary() -> impl Dictionary { TrieBuf::from([ (vec![syl![G, U, O, TONE2]], vec![("國", 1)]), diff --git a/src/conversion/fuzzy.rs b/src/conversion/fuzzy.rs index bfc632de..b728f5b0 100644 --- a/src/conversion/fuzzy.rs +++ b/src/conversion/fuzzy.rs @@ -1,6 +1,5 @@ -use crate::{conversion::Outcome, dictionary::LookupStrategy}; - use super::{ChewingEngine, ConversionEngine}; +use crate::{conversion::Outcome, dictionary::LookupStrategy}; /// Same conversion method as Chewing but uses fuzzy phrase search. #[derive(Debug, Default)] diff --git a/src/conversion/mod.rs b/src/conversion/mod.rs index 99a04e45..cc1cfa3a 100644 --- a/src/conversion/mod.rs +++ b/src/conversion/mod.rs @@ -10,12 +10,11 @@ use std::{ fmt::Debug, }; -use crate::{dictionary::Dictionary, zhuyin::Syllable}; - pub use self::chewing::ChewingEngine; pub use self::fuzzy::FuzzyChewingEngine; pub use self::simple::SimpleEngine; pub(crate) use self::symbol::{full_width_symbol_input, special_symbol_input}; +use crate::{dictionary::Dictionary, zhuyin::Syllable}; /// Converts a composition buffer to list of intervals. /// diff --git a/src/conversion/simple.rs b/src/conversion/simple.rs index d5c1fb72..a0cf4523 100644 --- a/src/conversion/simple.rs +++ b/src/conversion/simple.rs @@ -1,10 +1,9 @@ +use super::{Composition, ConversionEngine, Interval}; use crate::{ conversion::Outcome, dictionary::{Dictionary, LookupStrategy}, }; -use super::{Composition, ConversionEngine, Interval}; - /// Simple engine does not perform any intelligent conversion. #[derive(Debug, Default)] pub struct SimpleEngine; @@ -65,6 +64,7 @@ impl ConversionEngine for SimpleEngine { #[cfg(test)] mod tests { + use super::SimpleEngine; use crate::{ conversion::{Composition, Interval, Outcome, Symbol}, dictionary::{Dictionary, TrieBuf}, @@ -72,8 +72,6 @@ mod tests { zhuyin::Bopomofo::*, }; - use super::SimpleEngine; - fn test_dictionary() -> impl Dictionary { TrieBuf::from([ (vec![syl![G, U, O, TONE2]], vec![("國", 1)]), diff --git a/src/dictionary/layered.rs b/src/dictionary/layered.rs index cf431ff9..77fae530 100644 --- a/src/dictionary/layered.rs +++ b/src/dictionary/layered.rs @@ -3,14 +3,13 @@ use std::{ iter, }; -use log::error; - -use crate::zhuyin::Syllable; +use tracing::error; use super::{ Dictionary, DictionaryInfo, DictionaryMut, Entries, LookupStrategy, Phrase, UpdateDictionaryError, }; +use crate::zhuyin::Syllable; /// A collection of dictionaries that returns the union of the lookup results. /// # Examples @@ -220,6 +219,7 @@ mod tests { io::{Cursor, Seek}, }; + use super::Layered; use crate::{ dictionary::{ Dictionary, DictionaryBuilder, DictionaryMut, LookupStrategy, Phrase, Trie, TrieBuf, @@ -229,8 +229,6 @@ mod tests { zhuyin::Bopomofo, }; - use super::Layered; - #[test] fn test_entries() -> Result<(), Box> { let sys_dict = TrieBuf::from([( diff --git a/src/dictionary/loader.rs b/src/dictionary/loader.rs index dbd0d97e..01b2986d 100644 --- a/src/dictionary/loader.rs +++ b/src/dictionary/loader.rs @@ -7,17 +7,16 @@ use std::{ path::{Path, PathBuf}, }; -use log::{error, info}; +use tracing::{error, info}; +#[cfg(feature = "sqlite")] +use super::SqliteDictionary; +use super::{Dictionary, TrieBuf, uhash}; use crate::{ editor::{AbbrevTable, SymbolSelector}, path::{find_files_by_names, find_path_by_files, sys_path_from_env_var, userphrase_path}, }; -#[cfg(feature = "sqlite")] -use super::SqliteDictionary; -use super::{Dictionary, TrieBuf, uhash}; - const UD_UHASH_FILE_NAME: &str = "uhash.dat"; // const UD_TRIE_FILE_NAME: &str = "chewing.dat"; const UD_SQLITE_FILE_NAME: &str = "chewing.sqlite3"; diff --git a/src/dictionary/mod.rs b/src/dictionary/mod.rs index bce420a7..a1929b7c 100644 --- a/src/dictionary/mod.rs +++ b/src/dictionary/mod.rs @@ -10,8 +10,6 @@ use std::{ path::Path, }; -use crate::zhuyin::Syllable; - pub use layered::Layered; pub use loader::{ DEFAULT_DICT_NAMES, LoadDictionaryError, SingleDictionaryLoader, SystemDictionaryLoader, @@ -22,6 +20,8 @@ pub use sqlite::{SqliteDictionary, SqliteDictionaryBuilder, SqliteDictionaryErro pub use trie::{Trie, TrieBuilder, TrieOpenOptions, TrieStatistics}; pub use trie_buf::TrieBuf; +use crate::zhuyin::Syllable; + mod layered; mod loader; #[cfg(feature = "sqlite")] diff --git a/src/dictionary/sqlite.rs b/src/dictionary/sqlite.rs index 86d723f4..f6ce52b0 100644 --- a/src/dictionary/sqlite.rs +++ b/src/dictionary/sqlite.rs @@ -8,12 +8,11 @@ use std::{ use rusqlite::{Connection, Error as RusqliteError, OpenFlags, OptionalExtension, params}; -use crate::zhuyin::Syllable; - use super::{ BuildDictionaryError, Dictionary, DictionaryBuilder, DictionaryInfo, DictionaryMut, Entries, LookupStrategy, Phrase, UpdateDictionaryError, }; +use crate::zhuyin::Syllable; const APPLICATION_ID: u32 = 0x43484557; // 'CHEW' in big-endian const USER_VERSION: u32 = 0; @@ -592,6 +591,7 @@ mod tests { use rusqlite::{Connection, params}; use tempfile::{NamedTempFile, tempdir}; + use super::SqliteDictionary; use crate::{ dictionary::{ Dictionary, DictionaryBuilder, DictionaryMut, LookupStrategy, Phrase, @@ -601,8 +601,6 @@ mod tests { zhuyin::Bopomofo, }; - use super::SqliteDictionary; - #[test] fn migration_from_userphrase_v1() { let temp_path = NamedTempFile::new() diff --git a/src/dictionary/trie.rs b/src/dictionary/trie.rs index e92e2acd..304c695f 100644 --- a/src/dictionary/trie.rs +++ b/src/dictionary/trie.rs @@ -17,14 +17,13 @@ use der::{ SliceReader, Tag, TagMode, TagNumber, Tagged, Writer, asn1::{ContextSpecificRef, OctetStringRef, Utf8StringRef}, }; -use log::{error, warn}; - -use crate::zhuyin::Syllable; +use tracing::{error, warn}; use super::{ BuildDictionaryError, Dictionary, DictionaryBuilder, DictionaryInfo, Entries, LookupStrategy, Phrase, }; +use crate::zhuyin::Syllable; const DICT_FORMAT_VERSION: u8 = 0; @@ -1188,6 +1187,7 @@ mod tests { num::NonZeroUsize, }; + use super::{Trie, TrieBuilder}; use crate::{ dictionary::{ Dictionary, DictionaryBuilder, DictionaryInfo, LookupStrategy, Phrase, TrieOpenOptions, @@ -1197,8 +1197,6 @@ mod tests { zhuyin::Bopomofo, }; - use super::{Trie, TrieBuilder}; - #[test] fn test_tree_construction() -> Result<(), Box> { let mut builder = TrieBuilder::new(); diff --git a/src/dictionary/trie_buf.rs b/src/dictionary/trie_buf.rs index 5beb2aa5..85fc4c13 100644 --- a/src/dictionary/trie_buf.rs +++ b/src/dictionary/trie_buf.rs @@ -7,14 +7,13 @@ use std::{ thread::{self, JoinHandle}, }; -use log::{error, info}; - -use crate::zhuyin::Syllable; +use tracing::{error, info}; use super::{ BuildDictionaryError, Dictionary, DictionaryBuilder, DictionaryInfo, DictionaryMut, Entries, LookupStrategy, Phrase, Trie, TrieBuilder, UpdateDictionaryError, }; +use crate::zhuyin::Syllable; /// A mutable dictionary backed by a Trie and a BTreeMap. #[derive(Debug)] @@ -374,14 +373,13 @@ impl Drop for TrieBuf { mod tests { use std::error::Error; + use super::{Dictionary, TrieBuf}; use crate::{ dictionary::{DictionaryMut, LookupStrategy, Phrase}, syl, zhuyin::Bopomofo::*, }; - use super::{Dictionary, TrieBuf}; - #[test] fn create_new_dictionary_in_memory_and_query() -> Result<(), Box> { let tmp_dir = tempfile::tempdir()?; diff --git a/src/dictionary/uhash.rs b/src/dictionary/uhash.rs index 1f7381b0..a6315818 100644 --- a/src/dictionary/uhash.rs +++ b/src/dictionary/uhash.rs @@ -17,9 +17,8 @@ use std::{ str::{self, FromStr}, }; -use crate::zhuyin::Syllable; - use super::Phrase; +use crate::zhuyin::Syllable; const BIN_FIELD_SIZE: usize = 125; const BIN_HASH_SIG: &str = "CBiH"; @@ -127,9 +126,8 @@ pub(crate) fn try_load_bin(mut input: R) -> io::Result Result<(), Box> { let file = NamedTempFile::new()?; diff --git a/src/editor/composition_editor.rs b/src/editor/composition_editor.rs index 18fcbb0e..9d8ea6d7 100644 --- a/src/editor/composition_editor.rs +++ b/src/editor/composition_editor.rs @@ -2,7 +2,7 @@ use std::cmp::min; -use log::warn; +use tracing::warn; use crate::conversion::{Composition, Gap, Interval, Symbol}; diff --git a/src/editor/estimate.rs b/src/editor/estimate.rs index 7c022df6..b0678833 100644 --- a/src/editor/estimate.rs +++ b/src/editor/estimate.rs @@ -86,9 +86,8 @@ impl UserFreqEstimate for LaxUserFreqEstimate { #[cfg(test)] mod tests { - use crate::{dictionary::TrieBuf, editor::UserFreqEstimate, syl}; - use super::LaxUserFreqEstimate; + use crate::{dictionary::TrieBuf, editor::UserFreqEstimate, syl}; #[test] fn load_from_dictionary() { diff --git a/src/editor/mod.rs b/src/editor/mod.rs index 7a5d8ed4..0feabe60 100644 --- a/src/editor/mod.rs +++ b/src/editor/mod.rs @@ -14,10 +14,15 @@ use std::{ mem, }; -pub use self::{abbrev::AbbrevTable, selection::symbol::SymbolSelector}; pub use estimate::{LaxUserFreqEstimate, UserFreqEstimate}; -use log::{debug, error, info, trace, warn}; +use tracing::{debug, error, info, trace, warn}; +pub use self::{abbrev::AbbrevTable, selection::symbol::SymbolSelector}; +use self::{ + composition_editor::CompositionEditor, + selection::{phrase::PhraseSelector, symbol::SpecialSymbolSelector}, + zhuyin_layout::{KeyBehavior, Standard, SyllableEditor}, +}; use crate::{ conversion::{ ChewingEngine, ConversionEngine, Interval, Symbol, full_width_symbol_input, @@ -31,12 +36,6 @@ use crate::{ zhuyin::Syllable, }; -use self::{ - composition_editor::CompositionEditor, - selection::{phrase::PhraseSelector, symbol::SpecialSymbolSelector}, - zhuyin_layout::{KeyBehavior, Standard, SyllableEditor}, -}; - #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum LanguageMode { Chinese, @@ -1548,6 +1547,8 @@ impl State for Highlighting { mod tests { use estimate::LaxUserFreqEstimate; + use super::collect_new_phrases; + use super::{BasicEditor, Editor}; use crate::{ conversion::{ChewingEngine, Interval, Symbol}, dictionary::{Layered, TrieBuf}, @@ -1561,9 +1562,6 @@ mod tests { zhuyin::Bopomofo as bpmf, }; - use super::collect_new_phrases; - use super::{BasicEditor, Editor}; - const CAPSLOCK_EVENT: KeyboardEvent = KeyboardEvent::builder() .code(keycode::KEY_CAPSLOCK) .ksym(keysym::SYM_CAPSLOCK) diff --git a/src/editor/selection/phrase.rs b/src/editor/selection/phrase.rs index cf99b6eb..96d56e47 100644 --- a/src/editor/selection/phrase.rs +++ b/src/editor/selection/phrase.rs @@ -261,6 +261,7 @@ impl PhraseSelector { #[cfg(test)] mod tests { + use super::PhraseSelector; use crate::{ conversion::{Composition, Interval, Symbol}, dictionary::{LookupStrategy, TrieBuf}, @@ -268,8 +269,6 @@ mod tests { zhuyin::Bopomofo::*, }; - use super::PhraseSelector; - #[test] fn init_when_cursor_end_of_buffer_syllable() { let mut com = Composition::new(); diff --git a/src/editor/selection/symbol.rs b/src/editor/selection/symbol.rs index 94faf905..d1337aad 100644 --- a/src/editor/selection/symbol.rs +++ b/src/editor/selection/symbol.rs @@ -162,9 +162,8 @@ impl SpecialSymbolSelector { mod tests { use std::io; - use crate::conversion::Symbol; - use super::SymbolSelector; + use crate::conversion::Symbol; #[test] fn select_level_one_leaf() { diff --git a/src/editor/zhuyin_layout/dc26.rs b/src/editor/zhuyin_layout/dc26.rs index f76705ad..e3ca4237 100644 --- a/src/editor/zhuyin_layout/dc26.rs +++ b/src/editor/zhuyin_layout/dc26.rs @@ -1,13 +1,12 @@ //! Dai Chien CP26 +use super::{KeyBehavior, SyllableEditor}; use crate::input::keycode::*; use crate::{ input::KeyboardEvent, zhuyin::{Bopomofo, Syllable}, }; -use super::{KeyBehavior, SyllableEditor}; - /// TODO: docs #[derive(Debug, Clone, Copy)] pub struct DaiChien26 { diff --git a/src/editor/zhuyin_layout/et.rs b/src/editor/zhuyin_layout/et.rs index 0e644d53..6db1f15b 100644 --- a/src/editor/zhuyin_layout/et.rs +++ b/src/editor/zhuyin_layout/et.rs @@ -2,14 +2,13 @@ //! //! Another commonly used keyboard layout on older IBM PC. +use super::{KeyBehavior, SyllableEditor}; use crate::input::keycode::*; use crate::{ input::KeyboardEvent, zhuyin::{Bopomofo, BopomofoKind, Syllable}, }; -use super::{KeyBehavior, SyllableEditor}; - /// TODO: docs #[derive(Debug, Clone, Copy)] pub struct Et { @@ -125,13 +124,12 @@ impl SyllableEditor for Et { #[cfg(test)] mod test { + use super::Et; use crate::{ editor::zhuyin_layout::{KeyBehavior, SyllableEditor}, input::{KeyboardEvent, keycode::KEY_SPACE, keysym::SYM_SPACE}, }; - use super::Et; - #[test] fn space() { let mut editor = Et::new(); diff --git a/src/editor/zhuyin_layout/et26.rs b/src/editor/zhuyin_layout/et26.rs index b413c319..aca2e990 100644 --- a/src/editor/zhuyin_layout/et26.rs +++ b/src/editor/zhuyin_layout/et26.rs @@ -1,5 +1,6 @@ //! ET26 (倚天26鍵) +use super::{KeyBehavior, SyllableEditor}; use crate::{ input::{ KeyboardEvent, @@ -9,8 +10,6 @@ use crate::{ zhuyin::{Bopomofo, BopomofoKind, Syllable}, }; -use super::{KeyBehavior, SyllableEditor}; - /// TODO: docs #[derive(Debug, Clone, Copy)] pub struct Et26 { diff --git a/src/editor/zhuyin_layout/ginyieh.rs b/src/editor/zhuyin_layout/ginyieh.rs index 66429f11..25a1edc7 100644 --- a/src/editor/zhuyin_layout/ginyieh.rs +++ b/src/editor/zhuyin_layout/ginyieh.rs @@ -2,14 +2,13 @@ //! //! Another commonly used keyboard layout on older IBM PC. +use super::{KeyBehavior, SyllableEditor}; use crate::input::keycode::*; use crate::{ input::KeyboardEvent, zhuyin::{Bopomofo, BopomofoKind, Syllable}, }; -use super::{KeyBehavior, SyllableEditor}; - /// TODO: docs #[derive(Debug, Clone, Copy)] pub struct GinYieh { @@ -125,13 +124,12 @@ impl SyllableEditor for GinYieh { #[cfg(test)] mod test { + use super::GinYieh; use crate::{ editor::zhuyin_layout::{KeyBehavior, SyllableEditor}, input::{KeyboardEvent, keycode::KEY_SPACE, keysym::SYM_SPACE}, }; - use super::GinYieh; - #[test] fn space() { let mut editor = GinYieh::new(); diff --git a/src/editor/zhuyin_layout/hsu.rs b/src/editor/zhuyin_layout/hsu.rs index b6407b13..d48dd9bf 100644 --- a/src/editor/zhuyin_layout/hsu.rs +++ b/src/editor/zhuyin_layout/hsu.rs @@ -1,13 +1,12 @@ //! Hsu keyboard layout +use super::{KeyBehavior, SyllableEditor}; use crate::{ input::KeyboardEvent, syl, zhuyin::{Bopomofo, BopomofoKind, Syllable}, }; -use super::{KeyBehavior, SyllableEditor}; - /// TODO: docs #[derive(Debug, Clone, Copy)] pub struct Hsu { @@ -295,6 +294,7 @@ impl SyllableEditor for Hsu { #[cfg(test)] mod test { + use super::Hsu; use crate::{ editor::zhuyin_layout::SyllableEditor, input::{ @@ -304,8 +304,6 @@ mod test { zhuyin::Bopomofo, }; - use super::Hsu; - fn map_key(ksym: Keysym) -> KeyboardEvent { KeyboardEvent::builder().ksym(ksym).build() } diff --git a/src/editor/zhuyin_layout/ibm.rs b/src/editor/zhuyin_layout/ibm.rs index 92e6c0b0..2acb348d 100644 --- a/src/editor/zhuyin_layout/ibm.rs +++ b/src/editor/zhuyin_layout/ibm.rs @@ -2,14 +2,13 @@ //! //! Another commonly used keyboard layout on older IBM PC. +use super::{KeyBehavior, SyllableEditor}; use crate::input::keycode::*; use crate::{ input::KeyboardEvent, zhuyin::{Bopomofo, BopomofoKind, Syllable}, }; -use super::{KeyBehavior, SyllableEditor}; - /// TODO: docs #[derive(Debug, Clone, Copy)] pub struct Ibm { @@ -125,13 +124,12 @@ impl SyllableEditor for Ibm { #[cfg(test)] mod test { + use super::Ibm; use crate::{ editor::zhuyin_layout::{KeyBehavior, SyllableEditor}, input::{KeyboardEvent, keycode::KEY_SPACE, keysym::SYM_SPACE}, }; - use super::Ibm; - #[test] fn space() { let mut editor = Ibm::new(); diff --git a/src/editor/zhuyin_layout/mod.rs b/src/editor/zhuyin_layout/mod.rs index 85b36b51..7a39125d 100644 --- a/src/editor/zhuyin_layout/mod.rs +++ b/src/editor/zhuyin_layout/mod.rs @@ -20,8 +20,6 @@ use std::{ str::FromStr, }; -use crate::{input::KeyboardEvent, zhuyin::Syllable}; - pub use self::{ dc26::DaiChien26, et::Et, @@ -32,6 +30,7 @@ pub use self::{ pinyin::{Pinyin, PinyinVariant}, standard::Standard, }; +use crate::{input::KeyboardEvent, zhuyin::Syllable}; mod dc26; mod et; diff --git a/src/editor/zhuyin_layout/pinyin.rs b/src/editor/zhuyin_layout/pinyin.rs index 339d087d..76e397a5 100644 --- a/src/editor/zhuyin_layout/pinyin.rs +++ b/src/editor/zhuyin_layout/pinyin.rs @@ -1,12 +1,11 @@ //! Pinyin +use super::{KeyBehavior, SyllableEditor}; use crate::{ input::{KeyboardEvent, keysym}, zhuyin::{Bopomofo, Syllable}, }; -use super::{KeyBehavior, SyllableEditor}; - const MAX_PINYIN_LEN: usize = 10; /// TODO: docs @@ -348,9 +347,8 @@ macro_rules! fin { mod table { - use crate::{syl, zhuyin::Bopomofo::*}; - use super::{AmbiguousMapEntry, FinalMapEntry, InitialMapEntry}; + use crate::{syl, zhuyin::Bopomofo::*}; pub(super) const COMMON_MAPPING: [AmbiguousMapEntry; 18] = [ // Special cases for WG @@ -529,6 +527,7 @@ mod table { #[cfg(test)] mod tests { + use super::Pinyin; use crate::{ editor::zhuyin_layout::SyllableEditor, input::{ @@ -539,8 +538,6 @@ mod tests { zhuyin::Bopomofo, }; - use super::Pinyin; - fn map_key(ksym: Keysym) -> KeyboardEvent { KeyboardEvent::builder().ksym(ksym).build() } diff --git a/src/editor/zhuyin_layout/standard.rs b/src/editor/zhuyin_layout/standard.rs index 82f4e11c..f1402bab 100644 --- a/src/editor/zhuyin_layout/standard.rs +++ b/src/editor/zhuyin_layout/standard.rs @@ -3,14 +3,13 @@ //! Also known as the Dai Chien (大千) layout. It's the default layout on almost //! all platforms and the most commonly used one. +use super::{KeyBehavior, SyllableEditor}; use crate::input::keycode::*; use crate::{ input::KeyboardEvent, zhuyin::{Bopomofo, BopomofoKind, Syllable}, }; -use super::{KeyBehavior, SyllableEditor}; - /// TODO: docs #[derive(Debug, Clone, Copy)] pub struct Standard { @@ -126,13 +125,12 @@ impl SyllableEditor for Standard { #[cfg(test)] mod test { + use super::Standard; use crate::{ editor::zhuyin_layout::{KeyBehavior, SyllableEditor}, input::{KeyboardEvent, keycode::KEY_SPACE, keysym::SYM_SPACE}, }; - use super::Standard; - #[test] fn space() { let mut editor = Standard::new(); diff --git a/src/input.rs b/src/input.rs index 5a5d935a..1e69ec3e 100644 --- a/src/input.rs +++ b/src/input.rs @@ -256,11 +256,10 @@ impl KeyboardEventBuilder { #[cfg(test)] mod tests { - use crate::input::KeyState; - use super::KeyboardEvent; use super::keycode; use super::keysym; + use crate::input::KeyState; #[test] fn keyboard_event_builder() { diff --git a/src/path.rs b/src/path.rs index 9932460d..59d3919d 100644 --- a/src/path.rs +++ b/src/path.rs @@ -8,7 +8,7 @@ use std::{ path::{Path, PathBuf}, }; -use log::{info, warn}; +use tracing::{info, warn}; #[cfg(target_family = "windows")] const DEFAULT_SYS_PATH: &str = "C:\\Program Files\\ChewingTextService\\Dictionary"; diff --git a/src/zhuyin/bopomofo.rs b/src/zhuyin/bopomofo.rs index 061df555..fb44ea21 100644 --- a/src/zhuyin/bopomofo.rs +++ b/src/zhuyin/bopomofo.rs @@ -400,9 +400,8 @@ impl TryFrom for Bopomofo { #[cfg(test)] mod tests { - use crate::zhuyin::{BopomofoErrorKind, ParseBopomofoError}; - use super::Bopomofo; + use crate::zhuyin::{BopomofoErrorKind, ParseBopomofoError}; #[test] fn parse() { diff --git a/tests/test-logger.c b/tests/test-logger.c index c217de1e..38d31c5e 100644 --- a/tests/test-logger.c +++ b/tests/test-logger.c @@ -58,6 +58,7 @@ int main(int argc, char *argv[]) { putenv("CHEWING_PATH=" CHEWING_DATA_PREFIX); putenv("CHEWING_USER_PATH=" TEST_HASH_DIR); + putenv("RUST_LOG=debug"); test_set_logger(); test_set_null_logger(); diff --git a/tools/src/dump.rs b/tools/src/dump.rs index 4ca1135c..b643b68d 100644 --- a/tools/src/dump.rs +++ b/tools/src/dump.rs @@ -5,10 +5,9 @@ use std::{ }; use anyhow::{Result, bail}; -use chewing::dictionary::{Dictionary, Trie}; - #[cfg(feature = "sqlite")] use chewing::dictionary::SqliteDictionary; +use chewing::dictionary::{Dictionary, Trie}; use crate::flags; diff --git a/tools/src/init_database.rs b/tools/src/init_database.rs index 865966cb..507d56d7 100644 --- a/tools/src/init_database.rs +++ b/tools/src/init_database.rs @@ -1,3 +1,11 @@ +use std::{ + error::Error, + fmt::Display, + fs::{self, File}, + io::{BufRead, BufReader}, + path::Path, +}; + #[cfg(not(feature = "sqlite"))] use anyhow::bail; use anyhow::{Context, Result, anyhow}; @@ -7,13 +15,6 @@ use chewing::{ dictionary::{DictionaryBuilder, DictionaryInfo, TrieBuilder}, zhuyin::{Bopomofo, Syllable}, }; -use std::{ - error::Error, - fmt::Display, - fs::{self, File}, - io::{BufRead, BufReader}, - path::Path, -}; use crate::flags;