diff options
| author | mtul0729 <52401682+mtul0729@users.noreply.github.com> | 2025-03-26 08:34:00 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-03-26 08:34:00 +0800 |
| commit | dd8f3e4528d45b7602df7ea6380b92a87dc4f711 (patch) | |
| tree | faf8368ed6e06a78547959414710848ff19a06ff | |
| parent | a71e7c6be72965afd537aae076e0aee9e6f0755e (diff) | |
| download | aichat-dd8f3e4528d45b7602df7ea6380b92a87dc4f711.tar.gz | |
refactor: replace `lazy_static` with `std::sync::LazyLock` (#1246)
| -rw-r--r-- | Cargo.lock | 1 | ||||
| -rw-r--r-- | Cargo.toml | 1 | ||||
| -rw-r--r-- | src/client/access_token.rs | 7 | ||||
| -rw-r--r-- | src/client/common.rs | 19 | ||||
| -rw-r--r-- | src/config/role.rs | 6 | ||||
| -rw-r--r-- | src/config/session.rs | 5 | ||||
| -rw-r--r-- | src/render/markdown.rs | 15 | ||||
| -rw-r--r-- | src/repl/mod.rs | 67 | ||||
| -rw-r--r-- | src/utils/clipboard.rs | 6 | ||||
| -rw-r--r-- | src/utils/command.rs | 5 | ||||
| -rw-r--r-- | src/utils/mod.rs | 19 | ||||
| -rw-r--r-- | src/utils/request.rs | 38 | ||||
| -rw-r--r-- | src/utils/variables.rs | 5 |
13 files changed, 109 insertions, 85 deletions
@@ -71,7 +71,6 @@ dependencies = [ "inquire", "is-terminal", "json-patch", - "lazy_static", "log", "nu-ansi-term 0.50.1", "os_info", @@ -29,7 +29,6 @@ crossterm = "0.28.1" chrono = "0.4.23" bincode = "1.3.3" parking_lot = "0.12.1" -lazy_static = "1.4.0" fancy-regex = "0.14.0" base64 = "0.22.0" nu-ansi-term = "0.50.0" diff --git a/src/client/access_token.rs b/src/client/access_token.rs index 0f69d9a..e09e02c 100644 --- a/src/client/access_token.rs +++ b/src/client/access_token.rs @@ -2,11 +2,10 @@ use anyhow::{anyhow, Result}; use chrono::Utc; use indexmap::IndexMap; use parking_lot::RwLock; +use std::sync::LazyLock; -lazy_static::lazy_static! { - static ref ACCESS_TOKENS: RwLock<IndexMap<String, (String, i64)>> = - RwLock::new(IndexMap::new()); -} +static ACCESS_TOKENS: LazyLock<RwLock<IndexMap<String, (String, i64)>>> = + LazyLock::new(|| RwLock::new(IndexMap::new())); pub fn get_access_token(client_name: &str) -> Result<String> { ACCESS_TOKENS diff --git a/src/client/common.rs b/src/client/common.rs index 89e0367..3b89d11 100644 --- a/src/client/common.rs +++ b/src/client/common.rs @@ -16,18 +16,23 @@ use inquire::{ use reqwest::{Client as ReqwestClient, RequestBuilder}; use serde::Deserialize; use serde_json::{json, Value}; +use std::sync::LazyLock; use std::time::Duration; use tokio::sync::mpsc::unbounded_channel; const MODELS_YAML: &str = include_str!("../../models.yaml"); -lazy_static::lazy_static! { - pub static ref ALL_PROVIDER_MODELS: Vec<ProviderModels> = { - Config::loal_models_override().ok().unwrap_or_else(|| serde_yaml::from_str(MODELS_YAML).unwrap()) - }; - static ref EMBEDDING_MODEL_RE: Regex = Regex::new(r"((^|/)(bge-|e5-|uae-|gte-|text-)|embed|multilingual|minilm)").unwrap(); - static ref ESCAPE_SLASH_RE: Regex = Regex::new(r"(?<!\\)/").unwrap(); -} +pub static ALL_PROVIDER_MODELS: LazyLock<Vec<ProviderModels>> = LazyLock::new(|| { + Config::loal_models_override() + .ok() + .unwrap_or_else(|| serde_yaml::from_str(MODELS_YAML).unwrap()) +}); + +static EMBEDDING_MODEL_RE: LazyLock<Regex> = LazyLock::new(|| { + Regex::new(r"((^|/)(bge-|e5-|uae-|gte-|text-)|embed|multilingual|minilm)").unwrap() +}); + +static ESCAPE_SLASH_RE: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"(?<!\\)/").unwrap()); #[async_trait::async_trait] pub trait Client: Sync + Send { diff --git a/src/config/role.rs b/src/config/role.rs index cf5be62..9bdfe6c 100644 --- a/src/config/role.rs +++ b/src/config/role.rs @@ -7,6 +7,7 @@ use fancy_regex::Regex; use rust_embed::Embed; use serde::{Deserialize, Serialize}; use serde_json::Value; +use std::sync::LazyLock; pub const SHELL_ROLE: &str = "%shell%"; pub const EXPLAIN_SHELL_ROLE: &str = "%explain-shell%"; @@ -19,9 +20,8 @@ pub const INPUT_PLACEHOLDER: &str = "__INPUT__"; #[folder = "assets/roles/"] struct RolesAsset; -lazy_static::lazy_static! { - static ref RE_METADATA: Regex = Regex::new(r"(?s)-{3,}\s*(.*?)\s*-{3,}\s*(.*)").unwrap(); -} +static RE_METADATA: LazyLock<Regex> = + LazyLock::new(|| Regex::new(r"(?s)-{3,}\s*(.*?)\s*-{3,}\s*(.*)").unwrap()); pub trait RoleLike { fn to_role(&self) -> Role; diff --git a/src/config/session.rs b/src/config/session.rs index 2bc1b6c..a895e64 100644 --- a/src/config/session.rs +++ b/src/config/session.rs @@ -12,10 +12,9 @@ use serde_json::json; use std::collections::HashMap; use std::fs::{read_to_string, write}; use std::path::Path; +use std::sync::LazyLock; -lazy_static::lazy_static! { - static ref RE_AUTONAME_PREFIX: Regex = Regex::new(r"\d{8}T\d{6}-").unwrap(); -} +static RE_AUTONAME_PREFIX: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"\d{8}T\d{6}-").unwrap()); #[derive(Debug, Clone, Default, Deserialize, Serialize)] pub struct Session { diff --git a/src/render/markdown.rs b/src/render/markdown.rs index f5f532d..33cdf47 100644 --- a/src/render/markdown.rs +++ b/src/render/markdown.rs @@ -3,6 +3,7 @@ use anyhow::{anyhow, Context, Result}; use crossterm::style::{Color, Stylize}; use crossterm::terminal; use std::collections::HashMap; +use std::sync::LazyLock; use syntect::highlighting::{Color as SyntectColor, FontStyle, Style, Theme}; use syntect::parsing::SyntaxSet; use syntect::{easy::HighlightLines, parsing::SyntaxReference}; @@ -10,14 +11,12 @@ use syntect::{easy::HighlightLines, parsing::SyntaxReference}; /// Comes from <https://github.com/sharkdp/bat/raw/5e77ca37e89c873e4490b42ff556370dc5c6ba4f/assets/syntaxes.bin> const SYNTAXES: &[u8] = include_bytes!("../../assets/syntaxes.bin"); -lazy_static::lazy_static! { - static ref LANG_MAPS: HashMap<String, String> = { - let mut m = HashMap::new(); - m.insert("csharp".into(), "C#".into()); - m.insert("php".into(), "PHP Source".into()); - m - }; -} +static LANG_MAPS: LazyLock<HashMap<String, String>> = LazyLock::new(|| { + let mut m = HashMap::new(); + m.insert("csharp".into(), "C#".into()); + m.insert("php".into(), "PHP Source".into()); + m +}); pub struct MarkdownRender { options: RenderOptions, diff --git a/src/repl/mod.rs b/src/repl/mod.rs index d7ddb96..97d8f84 100644 --- a/src/repl/mod.rs +++ b/src/repl/mod.rs @@ -24,25 +24,30 @@ use reedline::{ ReedlineEvent, ReedlineMenu, ValidationResult, Validator, Vi, }; use reedline::{MenuBuilder, Signal}; +use std::sync::LazyLock; use std::{env, process}; const MENU_NAME: &str = "completion_menu"; -lazy_static::lazy_static! { - static ref REPL_COMMANDS: [ReplCommand; 36] = [ +static REPL_COMMANDS: LazyLock<[ReplCommand; 36]> = LazyLock::new(|| { + [ ReplCommand::new(".help", "Show this help guide", AssertState::pass()), ReplCommand::new(".info", "Show system info", AssertState::pass()), - ReplCommand::new(".edit config", "Modify configuration file", AssertState::False(StateFlags::AGENT)), + ReplCommand::new( + ".edit config", + "Modify configuration file", + AssertState::False(StateFlags::AGENT), + ), ReplCommand::new(".model", "Switch LLM model", AssertState::pass()), ReplCommand::new( ".prompt", "Set a temporary role using a prompt", - AssertState::False(StateFlags::SESSION | StateFlags::AGENT) + AssertState::False(StateFlags::SESSION | StateFlags::AGENT), ), ReplCommand::new( ".role", "Create or switch to a role", - AssertState::False(StateFlags::SESSION | StateFlags::AGENT) + AssertState::False(StateFlags::SESSION | StateFlags::AGENT), ), ReplCommand::new( ".info role", @@ -57,7 +62,10 @@ lazy_static::lazy_static! { ReplCommand::new( ".save role", "Save current role to file", - AssertState::TrueFalse(StateFlags::ROLE, StateFlags::SESSION_EMPTY | StateFlags::SESSION), + AssertState::TrueFalse( + StateFlags::ROLE, + StateFlags::SESSION_EMPTY | StateFlags::SESSION, + ), ), ReplCommand::new( ".exit role", @@ -72,12 +80,12 @@ lazy_static::lazy_static! { ReplCommand::new( ".empty session", "Clear session messages", - AssertState::True(StateFlags::SESSION) + AssertState::True(StateFlags::SESSION), ), ReplCommand::new( ".compress session", "Compress session messages", - AssertState::True(StateFlags::SESSION) + AssertState::True(StateFlags::SESSION), ), ReplCommand::new( ".info session", @@ -87,23 +95,23 @@ lazy_static::lazy_static! { ReplCommand::new( ".edit session", "Modify current session", - AssertState::True(StateFlags::SESSION_EMPTY | StateFlags::SESSION) + AssertState::True(StateFlags::SESSION_EMPTY | StateFlags::SESSION), ), ReplCommand::new( ".save session", "Save current session to file", - AssertState::True(StateFlags::SESSION_EMPTY | StateFlags::SESSION) + AssertState::True(StateFlags::SESSION_EMPTY | StateFlags::SESSION), ), ReplCommand::new( ".exit session", "Exit active session", - AssertState::True(StateFlags::SESSION_EMPTY | StateFlags::SESSION) + AssertState::True(StateFlags::SESSION_EMPTY | StateFlags::SESSION), ), ReplCommand::new(".agent", "Use an agent", AssertState::bare()), ReplCommand::new( ".starter", "Use a conversation starter", - AssertState::True(StateFlags::AGENT) + AssertState::True(StateFlags::AGENT), ), ReplCommand::new( ".edit agent-config", @@ -118,12 +126,12 @@ lazy_static::lazy_static! { ReplCommand::new( ".exit agent", "Leave agent", - AssertState::True(StateFlags::AGENT) + AssertState::True(StateFlags::AGENT), ), ReplCommand::new( ".rag", "Initialize or access RAG", - AssertState::False(StateFlags::AGENT) + AssertState::False(StateFlags::AGENT), ), ReplCommand::new( ".edit rag-docs", @@ -150,30 +158,35 @@ lazy_static::lazy_static! { "Leave RAG", AssertState::TrueFalse(StateFlags::RAG, StateFlags::AGENT), ), - ReplCommand::new( - ".macro", - "Execute a macro", - AssertState::pass() - ), + ReplCommand::new(".macro", "Execute a macro", AssertState::pass()), ReplCommand::new( ".file", "Include files, directories, URLs or commands", - AssertState::pass() + AssertState::pass(), + ), + ReplCommand::new( + ".continue", + "Continue previous response", + AssertState::pass(), ), - ReplCommand::new(".continue", "Continue previous response", AssertState::pass()), ReplCommand::new( ".regenerate", "Regenerate last response", - AssertState::pass() + AssertState::pass(), ), ReplCommand::new(".copy", "Copy last response", AssertState::pass()), ReplCommand::new(".set", "Modify runtime settings", AssertState::pass()), - ReplCommand::new(".delete", "Delete roles, sessions, RAGs, or agents", AssertState::pass()), + ReplCommand::new( + ".delete", + "Delete roles, sessions, RAGs, or agents", + AssertState::pass(), + ), ReplCommand::new(".exit", "Exit REPL", AssertState::pass()), - ]; - static ref COMMAND_RE: Regex = Regex::new(r"^\s*(\.\S*)\s*").unwrap(); - static ref MULTILINE_RE: Regex = Regex::new(r"(?s)^\s*:::\s*(.*)\s*:::\s*$").unwrap(); -} + ] +}); +static COMMAND_RE: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"^\s*(\.\S*)\s*").unwrap()); +static MULTILINE_RE: LazyLock<Regex> = + LazyLock::new(|| Regex::new(r"(?s)^\s*:::\s*(.*)\s*:::\s*$").unwrap()); pub struct Repl { config: GlobalConfig, diff --git a/src/utils/clipboard.rs b/src/utils/clipboard.rs index 23bb4f3..12e1655 100644 --- a/src/utils/clipboard.rs +++ b/src/utils/clipboard.rs @@ -1,8 +1,6 @@ #[cfg(not(any(target_os = "android", target_os = "emscripten")))] -lazy_static::lazy_static! { - static ref CLIPBOARD: std::sync::Arc<std::sync::Mutex<Option<arboard::Clipboard>>> = - std::sync::Arc::new(std::sync::Mutex::new(arboard::Clipboard::new().ok())); -} +static CLIPBOARD: std::sync::LazyLock<std::sync::Mutex<Option<arboard::Clipboard>>> = + std::sync::LazyLock::new(|| std::sync::Mutex::new(arboard::Clipboard::new().ok())); #[cfg(not(any(target_os = "android", target_os = "emscripten")))] pub fn set_text(text: &str) -> anyhow::Result<()> { diff --git a/src/utils/command.rs b/src/utils/command.rs index 300a471..14a40a4 100644 --- a/src/utils/command.rs +++ b/src/utils/command.rs @@ -12,10 +12,9 @@ use std::{ use anyhow::{anyhow, bail, Context, Result}; use dirs::home_dir; +use std::sync::LazyLock; -lazy_static::lazy_static! { - pub static ref SHELL: Shell = detect_shell(); -} +pub static SHELL: LazyLock<Shell> = LazyLock::new(detect_shell); pub struct Shell { pub name: String, diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 38617a6..98f2da1 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -27,15 +27,22 @@ use fancy_regex::Regex; use fuzzy_matcher::{skim::SkimMatcherV2, FuzzyMatcher}; use is_terminal::IsTerminal; use std::borrow::Cow; +use std::sync::LazyLock; use std::{env, path::PathBuf, process}; use unicode_segmentation::UnicodeSegmentation; -lazy_static::lazy_static! { - pub static ref CODE_BLOCK_RE: Regex = Regex::new(r"(?ms)```\w*(.*)```").unwrap(); - pub static ref THINK_TAG_RE: Regex = Regex::new(r"(?s)^\s*<think>.*?</think>(\s*|$)").unwrap(); - pub static ref IS_STDOUT_TERMINAL: bool = std::io::stdout().is_terminal(); - pub static ref NO_COLOR: bool = env::var("NO_COLOR").ok().and_then(|v| parse_bool(&v)).unwrap_or_default() || !*IS_STDOUT_TERMINAL; -} +pub static CODE_BLOCK_RE: LazyLock<Regex> = + LazyLock::new(|| Regex::new(r"(?ms)```\w*(.*)```").unwrap()); +pub static THINK_TAG_RE: LazyLock<Regex> = + LazyLock::new(|| Regex::new(r"(?s)^\s*<think>.*?</think>(\s*|$)").unwrap()); +pub static IS_STDOUT_TERMINAL: LazyLock<bool> = LazyLock::new(|| std::io::stdout().is_terminal()); +pub static NO_COLOR: LazyLock<bool> = LazyLock::new(|| { + env::var("NO_COLOR") + .ok() + .and_then(|v| parse_bool(&v)) + .unwrap_or_default() + || !*IS_STDOUT_TERMINAL +}); pub fn now() -> String { chrono::Local::now().to_rfc3339_opts(chrono::SecondsFormat::Secs, false) diff --git a/src/utils/request.rs b/src/utils/request.rs index 4516806..8cee0a0 100644 --- a/src/utils/request.rs +++ b/src/utils/request.rs @@ -8,6 +8,7 @@ use reqwest::Url; use scraper::{Html, Selector}; use serde::Deserialize; use serde_json::Value; +use std::sync::LazyLock; use std::{ collections::{HashMap, HashSet}, sync::Arc, @@ -26,28 +27,35 @@ const MAX_CRAWLS: usize = 5; const BREAK_ON_ERROR: bool = false; const USER_AGENT: &str = "curl/8.6.0"; -lazy_static::lazy_static! { - static ref CLIENT: Result<reqwest::Client> = { - let builder = reqwest::ClientBuilder::new().timeout(Duration::from_secs(16)); - let client = builder.build()?; - Ok(client) - }; +static CLIENT: LazyLock<Result<reqwest::Client>> = LazyLock::new(|| { + let builder = reqwest::ClientBuilder::new().timeout(Duration::from_secs(16)); + let client = builder.build()?; + Ok(client) +}); - static ref PRESET: Vec<(Regex, CrawlOptions)> = vec![ +static PRESET: LazyLock<Vec<(Regex, CrawlOptions)>> = LazyLock::new(|| { + vec![ ( Regex::new(r"github.com/([^/]+)/([^/]+)/tree/([^/]+)").unwrap(), - CrawlOptions { exclude: vec!["changelog".into(), "changes".into(), "license".into()], ..Default::default() } + CrawlOptions { + exclude: vec!["changelog".into(), "changes".into(), "license".into()], + ..Default::default() + }, ), ( Regex::new(r"github.com/([^/]+)/([^/]+)/wiki").unwrap(), - CrawlOptions { exclude: vec!["_history".into()], extract: Some("#wiki-body".into()), ..Default::default() } - - ) - ]; + CrawlOptions { + exclude: vec!["_history".into()], + extract: Some("#wiki-body".into()), + ..Default::default() + }, + ), + ] +}); - static ref EXTENSION_RE: Regex = Regex::new(r"\.[^.]+$").unwrap(); - static ref GITHUB_REPO_RE: Regex = Regex::new(r"^https://github\.com/([^/]+)/([^/]+)/tree/([^/]+)").unwrap(); -} +static EXTENSION_RE: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"\.[^.]+$").unwrap()); +static GITHUB_REPO_RE: LazyLock<Regex> = + LazyLock::new(|| Regex::new(r"^https://github\.com/([^/]+)/([^/]+)/tree/([^/]+)").unwrap()); pub async fn fetch(url: &str) -> Result<String> { let client = match *CLIENT { diff --git a/src/utils/variables.rs b/src/utils/variables.rs index 91c9912..bfec4ca 100644 --- a/src/utils/variables.rs +++ b/src/utils/variables.rs @@ -1,9 +1,8 @@ use super::*; use fancy_regex::{Captures, Regex}; +use std::sync::LazyLock; -lazy_static::lazy_static! { - pub static ref RE_VARIABLE: Regex = Regex::new(r"\{\{(\w+)\}\}").unwrap(); -} +pub static RE_VARIABLE: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"\{\{(\w+)\}\}").unwrap()); pub fn interpolate_variables(text: &mut String) { *text = RE_VARIABLE .replace_all(text, |caps: &Captures<'_>| { |
