summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormtul0729 <52401682+mtul0729@users.noreply.github.com>2025-03-26 08:34:00 +0800
committerGitHub <noreply@github.com>2025-03-26 08:34:00 +0800
commitdd8f3e4528d45b7602df7ea6380b92a87dc4f711 (patch)
treefaf8368ed6e06a78547959414710848ff19a06ff
parenta71e7c6be72965afd537aae076e0aee9e6f0755e (diff)
downloadaichat-dd8f3e4528d45b7602df7ea6380b92a87dc4f711.tar.gz
refactor: replace `lazy_static` with `std::sync::LazyLock` (#1246)
-rw-r--r--Cargo.lock1
-rw-r--r--Cargo.toml1
-rw-r--r--src/client/access_token.rs7
-rw-r--r--src/client/common.rs19
-rw-r--r--src/config/role.rs6
-rw-r--r--src/config/session.rs5
-rw-r--r--src/render/markdown.rs15
-rw-r--r--src/repl/mod.rs67
-rw-r--r--src/utils/clipboard.rs6
-rw-r--r--src/utils/command.rs5
-rw-r--r--src/utils/mod.rs19
-rw-r--r--src/utils/request.rs38
-rw-r--r--src/utils/variables.rs5
13 files changed, 109 insertions, 85 deletions
diff --git a/Cargo.lock b/Cargo.lock
index a25ad25..bfd9bf1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -71,7 +71,6 @@ dependencies = [
"inquire",
"is-terminal",
"json-patch",
- "lazy_static",
"log",
"nu-ansi-term 0.50.1",
"os_info",
diff --git a/Cargo.toml b/Cargo.toml
index 41a94bb..9424862 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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<'_>| {