diff options
Diffstat (limited to 'crates/turtle/src/atuin_client')
38 files changed, 534 insertions, 534 deletions
diff --git a/crates/turtle/src/atuin_client/api_client.rs b/crates/turtle/src/atuin_client/api_client.rs index 7955c2da..f3f2428a 100644 --- a/crates/turtle/src/atuin_client/api_client.rs +++ b/crates/turtle/src/atuin_client/api_client.rs @@ -40,7 +40,7 @@ static APP_USER_AGENT: &str = concat!("atuin/", env!("CARGO_PKG_VERSION"),); /// When both are available, Hub tokens are preferred as they provide unified /// authentication across CLI and Hub features. #[derive(Debug, Clone)] -pub enum AuthToken { +pub(crate) enum AuthToken { /// Legacy CLI session token, used with "Token {token}" header Token(String), } @@ -54,7 +54,7 @@ impl AuthToken { } } -pub struct Client<'a> { +pub(crate) struct Client<'a> { sync_addr: &'a str, client: reqwest::Client, } @@ -78,7 +78,7 @@ fn make_url(address: &str, path: &str) -> Result<String> { Ok(url.to_string()) } -pub async fn register( +pub(crate) async fn register( address: &str, username: &str, email: &str, @@ -116,7 +116,7 @@ pub async fn register( Ok(session) } -pub async fn login(address: &str, req: LoginRequest) -> Result<LoginResponse> { +pub(crate) async fn login(address: &str, req: LoginRequest) -> Result<LoginResponse> { ensure_crypto_provider(); let url = make_url(address, "/login")?; let client = reqwest::Client::new(); @@ -137,7 +137,7 @@ pub async fn login(address: &str, req: LoginRequest) -> Result<LoginResponse> { Ok(session) } -pub fn ensure_version(response: &Response) -> Result<bool> { +pub(crate) fn ensure_version(response: &Response) -> Result<bool> { let version = response.headers().get(ATUIN_HEADER_VERSION); let version = if let Some(version) = version { @@ -199,7 +199,7 @@ async fn handle_resp_error(resp: Response) -> Result<Response> { } impl<'a> Client<'a> { - pub fn new( + pub(crate) fn new( sync_addr: &'a str, auth: AuthToken, connect_timeout: u64, @@ -223,7 +223,7 @@ impl<'a> Client<'a> { }) } - pub async fn count(&self) -> Result<i64> { + pub(crate) async fn count(&self) -> Result<i64> { let url = make_url(self.sync_addr, "/sync/count")?; let url = Url::parse(url.as_str())?; @@ -243,7 +243,7 @@ impl<'a> Client<'a> { Ok(count.count) } - pub async fn status(&self) -> Result<StatusResponse> { + pub(crate) async fn status(&self) -> Result<StatusResponse> { let url = make_url(self.sync_addr, "/sync/status")?; let url = Url::parse(url.as_str())?; @@ -259,7 +259,7 @@ impl<'a> Client<'a> { Ok(status) } - pub async fn me(&self) -> Result<MeResponse> { + pub(crate) async fn me(&self) -> Result<MeResponse> { let url = make_url(self.sync_addr, "/api/v0/me")?; let url = Url::parse(url.as_str())?; @@ -271,7 +271,7 @@ impl<'a> Client<'a> { Ok(status) } - pub async fn get_history( + pub(crate) async fn get_history( &self, sync_ts: OffsetDateTime, history_ts: OffsetDateTime, @@ -296,7 +296,7 @@ impl<'a> Client<'a> { Ok(history) } - pub async fn post_history(&self, history: &[AddHistoryRequest]) -> Result<()> { + pub(crate) async fn post_history(&self, history: &[AddHistoryRequest]) -> Result<()> { let url = make_url(self.sync_addr, "/history")?; let url = Url::parse(url.as_str())?; @@ -306,7 +306,7 @@ impl<'a> Client<'a> { Ok(()) } - pub async fn delete_history(&self, h: History) -> Result<()> { + pub(crate) async fn delete_history(&self, h: History) -> Result<()> { let url = make_url(self.sync_addr, "/history")?; let url = Url::parse(url.as_str())?; @@ -324,7 +324,7 @@ impl<'a> Client<'a> { Ok(()) } - pub async fn delete_store(&self) -> Result<()> { + pub(crate) async fn delete_store(&self) -> Result<()> { let url = make_url(self.sync_addr, "/api/v0/store")?; let url = Url::parse(url.as_str())?; @@ -335,7 +335,7 @@ impl<'a> Client<'a> { Ok(()) } - pub async fn post_records(&self, records: &[Record<EncryptedData>]) -> Result<()> { + pub(crate) async fn post_records(&self, records: &[Record<EncryptedData>]) -> Result<()> { let url = make_url(self.sync_addr, "/api/v0/record")?; let url = Url::parse(url.as_str())?; @@ -347,7 +347,7 @@ impl<'a> Client<'a> { Ok(()) } - pub async fn next_records( + pub(crate) async fn next_records( &self, host: HostId, tag: String, @@ -374,7 +374,7 @@ impl<'a> Client<'a> { Ok(records) } - pub async fn record_status(&self) -> Result<RecordStatus> { + pub(crate) async fn record_status(&self) -> Result<RecordStatus> { let url = make_url(self.sync_addr, "/api/v0/record")?; let url = Url::parse(url.as_str())?; @@ -392,7 +392,7 @@ impl<'a> Client<'a> { Ok(index) } - pub async fn delete(&self) -> Result<()> { + pub(crate) async fn delete(&self) -> Result<()> { let url = make_url(self.sync_addr, "/account")?; let url = Url::parse(url.as_str())?; @@ -407,7 +407,7 @@ impl<'a> Client<'a> { } } - pub async fn change_password( + pub(crate) async fn change_password( &self, current_password: String, new_password: String, diff --git a/crates/turtle/src/atuin_client/auth.rs b/crates/turtle/src/atuin_client/auth.rs index b770c488..b260d433 100644 --- a/crates/turtle/src/atuin_client/auth.rs +++ b/crates/turtle/src/atuin_client/auth.rs @@ -15,7 +15,7 @@ use crate::atuin_client::settings::Settings; static APP_USER_AGENT: &str = concat!("atuin/", env!("CARGO_PKG_VERSION")); /// Result of an auth operation that may require 2FA. -pub enum AuthResponse { +pub(crate) enum AuthResponse { /// Operation succeeded; for login/register, contains the session token. /// `auth_type` indicates the kind of token: `Some("hub")` for Hub API /// tokens (prefixed `atapi_`), `Some("cli")` for legacy CLI session @@ -30,7 +30,7 @@ pub enum AuthResponse { } /// Result of a mutating account operation that may require 2FA. -pub enum MutateResponse { +pub(crate) enum MutateResponse { /// Operation completed successfully. Success, /// Two-factor authentication is required; the caller should prompt for a @@ -43,7 +43,7 @@ pub enum MutateResponse { /// CLI commands use this trait so they don't need to know which backend is /// active — they just prompt for input and call these methods. #[async_trait] -pub trait AuthClient: Send + Sync { +pub(crate) trait AuthClient: Send + Sync { /// Log in with username + password, optionally providing a TOTP code. async fn login(&self, username: &str, password: &str) -> Result<AuthResponse>; @@ -67,7 +67,7 @@ pub trait AuthClient: Send + Sync { } /// Resolve the appropriate [`AuthClient`] for the current settings. -pub async fn auth_client(settings: &Settings) -> Box<dyn AuthClient> { +pub(crate) async fn auth_client(settings: &Settings) -> Box<dyn AuthClient> { Box::new(LegacyAuthClient::new( &settings.sync_address, settings.session_token().await.ok(), @@ -80,7 +80,7 @@ pub async fn auth_client(settings: &Settings) -> Box<dyn AuthClient> { // Legacy backend — talks to the Rust sync server // --------------------------------------------------------------------------- -pub struct LegacyAuthClient { +pub(crate) struct LegacyAuthClient { address: String, session_token: Option<String>, connect_timeout: u64, @@ -88,7 +88,7 @@ pub struct LegacyAuthClient { } impl LegacyAuthClient { - pub fn new( + pub(crate) fn new( address: &str, session_token: Option<String>, connect_timeout: u64, diff --git a/crates/turtle/src/atuin_client/database.rs b/crates/turtle/src/atuin_client/database.rs index 27f46da5..1bfe93a7 100644 --- a/crates/turtle/src/atuin_client/database.rs +++ b/crates/turtle/src/atuin_client/database.rs @@ -35,31 +35,31 @@ use super::{ }; #[derive(Clone)] -pub struct Context { - pub session: String, - pub cwd: String, - pub hostname: String, - pub host_id: String, - pub git_root: Option<PathBuf>, +pub(crate) struct Context { + pub(crate) session: String, + pub(crate) cwd: String, + pub(crate) hostname: String, + pub(crate) host_id: String, + pub(crate) git_root: Option<PathBuf>, } #[derive(Default, Clone)] -pub struct OptFilters { - pub exit: Option<i64>, - pub exclude_exit: Option<i64>, - pub cwd: Option<String>, - pub exclude_cwd: Option<String>, - pub before: Option<String>, - pub after: Option<String>, - pub limit: Option<i64>, - pub offset: Option<i64>, - pub reverse: bool, - pub include_duplicates: bool, +pub(crate) struct OptFilters { + pub(crate) exit: Option<i64>, + pub(crate) exclude_exit: Option<i64>, + pub(crate) cwd: Option<String>, + pub(crate) exclude_cwd: Option<String>, + pub(crate) before: Option<String>, + pub(crate) after: Option<String>, + pub(crate) limit: Option<i64>, + pub(crate) offset: Option<i64>, + pub(crate) reverse: bool, + pub(crate) include_duplicates: bool, /// Author filter. Supports special values `$all-user` and `$all-agent`. - pub authors: Vec<String>, + pub(crate) authors: Vec<String>, } -pub async fn current_context() -> eyre::Result<Context> { +pub(crate) async fn current_context() -> eyre::Result<Context> { let session = env::var("ATUIN_SESSION").map_err(|_| { eyre::eyre!("Failed to find $ATUIN_SESSION in the environment. Check that you have correctly set up your shell.") })?; @@ -78,7 +78,7 @@ pub async fn current_context() -> eyre::Result<Context> { } impl Context { - pub fn from_history(entry: &History) -> Self { + pub(crate) fn from_history(entry: &History) -> Self { Context { session: entry.session.to_string(), cwd: entry.cwd.to_string(), @@ -132,7 +132,7 @@ fn get_session_start_time(session_id: &str) -> Option<i64> { } #[async_trait] -pub trait Database: Send + Sync + 'static { +pub(crate) trait Database: Send + Sync + 'static { async fn save(&self, h: &History) -> Result<()>; async fn save_bulk(&self, h: &[History]) -> Result<()>; @@ -186,12 +186,12 @@ pub trait Database: Send + Sync + 'static { // Intended for use on a developer machine and not a sync server. // TODO: implement IntoIterator #[derive(Debug, Clone)] -pub struct Sqlite { - pub pool: SqlitePool, +pub(crate) struct Sqlite { + pub(crate) pool: SqlitePool, } impl Sqlite { - pub async fn new(path: impl AsRef<Path>, timeout: f64) -> Result<Self> { + pub(crate) async fn new(path: impl AsRef<Path>, timeout: f64) -> Result<Self> { let path = path.as_ref(); debug!("opening sqlite database at {path:?}"); @@ -224,7 +224,7 @@ impl Sqlite { Ok(Self { pool }) } - pub async fn sqlite_version(&self) -> Result<String> { + pub(crate) async fn sqlite_version(&self) -> Result<String> { sqlx::query_scalar("SELECT sqlite_version()") .fetch_one(&self.pool) .await @@ -868,7 +868,7 @@ impl Database for Sqlite { } } -pub struct Paged { +pub(crate) struct Paged { database: Box<dyn Database + 'static>, page_size: usize, last_id: Option<String>, @@ -877,7 +877,7 @@ pub struct Paged { } impl Paged { - pub fn new( + pub(crate) fn new( database: Box<dyn Database + 'static>, page_size: usize, include_deleted: bool, @@ -892,7 +892,7 @@ impl Paged { } } - pub async fn next(&mut self) -> Result<Option<Vec<History>>> { + pub(crate) async fn next(&mut self) -> Result<Option<Vec<History>>> { let mut query = SqlBuilder::select_from(SqlName::new("history").alias("h").baquoted()); query.field("*").order_desc("id"); @@ -1434,12 +1434,12 @@ mod test { } } -pub struct QueryTokenizer<'a> { +pub(crate) struct QueryTokenizer<'a> { query: &'a str, last_pos: usize, } -pub enum QueryToken<'a> { +pub(crate) enum QueryToken<'a> { Match(&'a str, bool), MatchStart(&'a str, bool), MatchEnd(&'a str, bool), @@ -1449,7 +1449,7 @@ pub enum QueryToken<'a> { } impl<'a> QueryToken<'a> { - pub fn has_uppercase(&self) -> bool { + pub(crate) fn has_uppercase(&self) -> bool { match self { Self::Match(term, _) | Self::MatchStart(term, _) @@ -1459,7 +1459,7 @@ impl<'a> QueryToken<'a> { } } - pub fn is_inverse(&self) -> bool { + pub(crate) fn is_inverse(&self) -> bool { match self { Self::Match(_, inv) | Self::MatchStart(_, inv) @@ -1471,7 +1471,7 @@ impl<'a> QueryToken<'a> { } impl<'a> QueryTokenizer<'a> { - pub fn new(query: &'a str) -> Self { + pub(crate) fn new(query: &'a str) -> Self { Self { query, last_pos: 0 } } } diff --git a/crates/turtle/src/atuin_client/distro.rs b/crates/turtle/src/atuin_client/distro.rs index dead8355..00b92fe9 100644 --- a/crates/turtle/src/atuin_client/distro.rs +++ b/crates/turtle/src/atuin_client/distro.rs @@ -3,7 +3,7 @@ use std::process::Command; /// Detect the Linux distribution from the system, /// using system-specific release files and falling /// back to lsb_release. -pub fn detect_linux_distribution() -> String { +pub(crate) fn detect_linux_distribution() -> String { detect_from_os_release() .or_else(detect_from_debian_version) .or_else(detect_from_centos_release) diff --git a/crates/turtle/src/atuin_client/encryption.rs b/crates/turtle/src/atuin_client/encryption.rs index 20a0cd90..f5d4f20d 100644 --- a/crates/turtle/src/atuin_client/encryption.rs +++ b/crates/turtle/src/atuin_client/encryption.rs @@ -11,7 +11,7 @@ use std::{io::prelude::*, path::PathBuf}; use base64::prelude::{BASE64_STANDARD, Engine}; -pub use crypto_secretbox::Key; +pub(crate) use crypto_secretbox::Key; use crypto_secretbox::{ AeadCore, AeadInPlace, KeyInit, XSalsa20Poly1305, aead::{Nonce, OsRng}, @@ -25,19 +25,19 @@ use time::{OffsetDateTime, format_description::well_known::Rfc3339, macros::form use crate::atuin_client::{history::History, settings::Settings}; #[derive(Debug, Serialize, Deserialize)] -pub struct EncryptedHistory { - pub ciphertext: Vec<u8>, - pub nonce: Nonce<XSalsa20Poly1305>, +pub(crate) struct EncryptedHistory { + pub(crate) ciphertext: Vec<u8>, + pub(crate) nonce: Nonce<XSalsa20Poly1305>, } -pub fn generate_encoded_key() -> Result<(Key, String)> { +pub(crate) fn generate_encoded_key() -> Result<(Key, String)> { let key = XSalsa20Poly1305::generate_key(&mut OsRng); let encoded = encode_key(&key)?; Ok((key, encoded)) } -pub fn new_key(settings: &Settings) -> Result<Key> { +pub(crate) fn new_key(settings: &Settings) -> Result<Key> { let path = settings.key_path.as_str(); let path = PathBuf::from(path); @@ -54,7 +54,7 @@ pub fn new_key(settings: &Settings) -> Result<Key> { } // Loads the secret key, will create + save if it doesn't exist -pub fn load_key(settings: &Settings) -> Result<Key> { +pub(crate) fn load_key(settings: &Settings) -> Result<Key> { let path = settings.key_path.as_str(); let key = if PathBuf::from(path).exists() { @@ -67,7 +67,7 @@ pub fn load_key(settings: &Settings) -> Result<Key> { Ok(key) } -pub fn encode_key(key: &Key) -> Result<String> { +pub(crate) fn encode_key(key: &Key) -> Result<String> { let mut buf = vec![]; rmp::encode::write_array_len(&mut buf, key.len() as u32) .wrap_err("could not encode key to message pack")?; @@ -80,7 +80,7 @@ pub fn encode_key(key: &Key) -> Result<String> { Ok(buf) } -pub fn decode_key(key: String) -> Result<Key> { +pub(crate) fn decode_key(key: String) -> Result<Key> { use rmp::decode; let buf = BASE64_STANDARD @@ -118,7 +118,7 @@ pub fn decode_key(key: String) -> Result<Key> { } } -pub fn encrypt(history: &History, key: &Key) -> Result<EncryptedHistory> { +pub(crate) fn encrypt(history: &History, key: &Key) -> Result<EncryptedHistory> { // serialize with msgpack let mut buf = encode(history)?; @@ -133,7 +133,7 @@ pub fn encrypt(history: &History, key: &Key) -> Result<EncryptedHistory> { }) } -pub fn decrypt(mut encrypted_history: EncryptedHistory, key: &Key) -> Result<History> { +pub(crate) fn decrypt(mut encrypted_history: EncryptedHistory, key: &Key) -> Result<History> { XSalsa20Poly1305::new(key) .decrypt_in_place( &encrypted_history.nonce, diff --git a/crates/turtle/src/atuin_client/history.rs b/crates/turtle/src/atuin_client/history.rs index cef65115..6bc0bc38 100644 --- a/crates/turtle/src/atuin_client/history.rs +++ b/crates/turtle/src/atuin_client/history.rs @@ -16,18 +16,18 @@ use crate::atuin_client::utils::get_host_user; use time::OffsetDateTime; mod builder; -pub mod store; +pub(crate) mod store; /// Known AI agent author values. Used to expand `$all-agent` and `$all-user` filters. -pub const KNOWN_AGENTS: &[&str] = &["claude-code", "codex", "copilot", "pi"]; -pub const AUTHOR_FILTER_ALL_USER: &str = "$all-user"; -pub const AUTHOR_FILTER_ALL_AGENT: &str = "$all-agent"; +pub(crate) const KNOWN_AGENTS: &[&str] = &["claude-code", "codex", "copilot", "pi"]; +pub(crate) const AUTHOR_FILTER_ALL_USER: &str = "$all-user"; +pub(crate) const AUTHOR_FILTER_ALL_AGENT: &str = "$all-agent"; -pub fn is_known_agent(author: &str) -> bool { +pub(crate) fn is_known_agent(author: &str) -> bool { KNOWN_AGENTS.contains(&author) } -pub fn author_matches_filters(author: &str, filters: &[String]) -> bool { +pub(crate) fn author_matches_filters(author: &str, filters: &[String]) -> bool { filters.is_empty() || filters.iter().any(|filter| match filter.as_str() { AUTHOR_FILTER_ALL_USER => !is_known_agent(author), @@ -41,12 +41,12 @@ pub(crate) const HISTORY_VERSION_V1: &str = "v1"; const HISTORY_RECORD_VERSION_V0: u16 = 0; const HISTORY_RECORD_VERSION_V1: u16 = 1; pub(crate) const HISTORY_VERSION: &str = HISTORY_VERSION_V1; -pub const HISTORY_TAG: &str = "history"; +pub(crate) const HISTORY_TAG: &str = "history"; const HISTORY_AUTHOR_ENV: &str = "ATUIN_HISTORY_AUTHOR"; const HISTORY_INTENT_ENV: &str = "ATUIN_HISTORY_INTENT"; #[derive(Clone, Debug, Eq, PartialEq, Hash)] -pub struct HistoryId(pub String); +pub(crate) struct HistoryId(pub(crate) String); impl Display for HistoryId { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { @@ -74,51 +74,51 @@ impl From<String> for HistoryId { // New fields must be added to `History::{serialize,deserialize}` in a backwards // compatible way (sensible defaults and careful `nfields` handling). #[derive(Debug, Clone, PartialEq, Eq, sqlx::FromRow)] -pub struct History { +pub(crate) struct History { /// A client-generated ID, used to identify the entry when syncing. /// /// Stored as `client_id` in the database. - pub id: HistoryId, + pub(crate) id: HistoryId, /// When the command was run. - pub timestamp: OffsetDateTime, + pub(crate) timestamp: OffsetDateTime, /// How long the command took to run. - pub duration: i64, + pub(crate) duration: i64, /// The exit code of the command. - pub exit: i64, + pub(crate) exit: i64, /// The command that was run. - pub command: String, + pub(crate) command: String, /// The current working directory when the command was run. - pub cwd: String, + pub(crate) cwd: String, /// The session ID, associated with a terminal session. - pub session: String, + pub(crate) session: String, /// The hostname of the machine the command was run on. - pub hostname: String, + pub(crate) hostname: String, /// Who wrote this command (human user or automation/agent identity). - pub author: String, + pub(crate) author: String, /// Optional rationale for why the command was executed. - pub intent: Option<String>, + pub(crate) intent: Option<String>, /// Timestamp, which is set when the entry is deleted, allowing a soft delete. - pub deleted_at: Option<OffsetDateTime>, + pub(crate) deleted_at: Option<OffsetDateTime>, } #[derive(Debug, Clone, PartialEq, Eq, sqlx::FromRow)] -pub struct HistoryStats { +pub(crate) struct HistoryStats { /// The command that was ran after this one in the session - pub next: Option<History>, + pub(crate) next: Option<History>, /// /// The command that was ran before this one in the session - pub previous: Option<History>, + pub(crate) previous: Option<History>, /// How many times has this command been ran? - pub total: u64, + pub(crate) total: u64, - pub average_duration: u64, + pub(crate) average_duration: u64, - pub exits: Vec<(i64, i64)>, + pub(crate) exits: Vec<(i64, i64)>, - pub day_of_week: Vec<(String, i64)>, + pub(crate) day_of_week: Vec<(String, i64)>, - pub duration_over_time: Vec<(String, i64)>, + pub(crate) duration_over_time: Vec<(String, i64)>, } impl History { @@ -177,7 +177,7 @@ impl History { } } - pub fn serialize(&self) -> Result<DecryptedData> { + pub(crate) fn serialize(&self) -> Result<DecryptedData> { // This is pretty much the same as what we used for the old history, with one difference - // it uses integers for timestamps rather than a string format. @@ -366,7 +366,7 @@ impl History { }) } - pub fn deserialize(bytes: &[u8], version: &str) -> Result<History> { + pub(crate) fn deserialize(bytes: &[u8], version: &str) -> Result<History> { match version { HISTORY_VERSION_V0 => Self::deserialize_v0(bytes), HISTORY_VERSION_V1 => Self::deserialize_v1(bytes), @@ -416,7 +416,7 @@ impl History { /// .build() /// .into(); /// ``` - pub fn import() -> builder::HistoryImportedBuilder { + pub(crate) fn import() -> builder::HistoryImportedBuilder { builder::HistoryImported::builder() } @@ -450,7 +450,7 @@ impl History { /// .build() /// .into(); /// ``` - pub fn capture() -> builder::HistoryCapturedBuilder { + pub(crate) fn capture() -> builder::HistoryCapturedBuilder { builder::HistoryCaptured::builder() } @@ -492,7 +492,7 @@ impl History { /// .build() /// .into(); /// ``` - pub fn daemon() -> builder::HistoryDaemonCaptureBuilder { + pub(crate) fn daemon() -> builder::HistoryDaemonCaptureBuilder { builder::HistoryDaemonCapture::builder() } @@ -518,15 +518,15 @@ impl History { /// .build() /// .into(); /// ``` - pub fn from_db() -> builder::HistoryFromDbBuilder { + pub(crate) fn from_db() -> builder::HistoryFromDbBuilder { builder::HistoryFromDb::builder() } - pub fn success(&self) -> bool { + pub(crate) fn success(&self) -> bool { self.exit == 0 || self.duration == -1 } - pub fn should_save(&self, settings: &Settings) -> bool { + pub(crate) fn should_save(&self, settings: &Settings) -> bool { !(self.command.starts_with(' ') || self.command.is_empty() || settings.history_filter.is_match(&self.command) diff --git a/crates/turtle/src/atuin_client/history/builder.rs b/crates/turtle/src/atuin_client/history/builder.rs index 72a505fd..50a9d2af 100644 --- a/crates/turtle/src/atuin_client/history/builder.rs +++ b/crates/turtle/src/atuin_client/history/builder.rs @@ -6,7 +6,7 @@ use super::History; /// /// The only two required fields are `timestamp` and `command`. #[derive(Debug, Clone, TypedBuilder)] -pub struct HistoryImported { +pub(crate) struct HistoryImported { timestamp: time::OffsetDateTime, #[builder(setter(into))] command: String, @@ -49,7 +49,7 @@ impl From<HistoryImported> for History { /// so it doesn't have any fields which are known only after /// the command is finished, such as `exit` or `duration`. #[derive(Debug, Clone, TypedBuilder)] -pub struct HistoryCaptured { +pub(crate) struct HistoryCaptured { timestamp: time::OffsetDateTime, #[builder(setter(into))] command: String, @@ -82,7 +82,7 @@ impl From<HistoryCaptured> for History { /// /// All fields are required, as they are all present in the database. #[derive(Debug, Clone, TypedBuilder)] -pub struct HistoryFromDb { +pub(crate) struct HistoryFromDb { id: String, timestamp: time::OffsetDateTime, command: String, @@ -120,7 +120,7 @@ impl From<HistoryFromDb> for History { /// For the old setup, we could just rely on History::new to read some of the missing /// data. This is no longer the case. #[derive(Debug, Clone, TypedBuilder)] -pub struct HistoryDaemonCapture { +pub(crate) struct HistoryDaemonCapture { timestamp: time::OffsetDateTime, #[builder(setter(into))] command: String, diff --git a/crates/turtle/src/atuin_client/history/store.rs b/crates/turtle/src/atuin_client/history/store.rs index 66d9db47..b2265698 100644 --- a/crates/turtle/src/atuin_client/history/store.rs +++ b/crates/turtle/src/atuin_client/history/store.rs @@ -14,14 +14,14 @@ use crate::atuin_common::record::{DecryptedData, Host, HostId, Record, RecordId, use super::{HISTORY_TAG, HISTORY_VERSION, HISTORY_VERSION_V0, History, HistoryId}; #[derive(Debug, Clone)] -pub struct HistoryStore { - pub store: SqliteStore, - pub host_id: HostId, - pub encryption_key: [u8; 32], +pub(crate) struct HistoryStore { + pub(crate) store: SqliteStore, + pub(crate) host_id: HostId, + pub(crate) encryption_key: [u8; 32], } #[derive(Debug, Eq, PartialEq, Clone)] -pub enum HistoryRecord { +pub(crate) enum HistoryRecord { Create(History), // Create a history record Delete(HistoryId), // Delete a history record, identified by ID } @@ -39,7 +39,7 @@ impl HistoryRecord { /// twice. /// /// Deletion simply refers to the history by ID - pub fn serialize(&self) -> Result<DecryptedData> { + pub(crate) fn serialize(&self) -> Result<DecryptedData> { // probably don't actually need to use rmp here, but if we ever need to extend it, it's a // nice wrapper around raw byte stuff use rmp::encode; @@ -65,7 +65,7 @@ impl HistoryRecord { Ok(DecryptedData(output)) } - pub fn deserialize(bytes: &DecryptedData, version: &str) -> Result<Self> { + pub(crate) fn deserialize(bytes: &DecryptedData, version: &str) -> Result<Self> { use rmp::decode; fn error_report<E: std::fmt::Debug>(err: E) -> eyre::Report { @@ -110,7 +110,7 @@ impl HistoryRecord { } impl HistoryStore { - pub fn new(store: SqliteStore, host_id: HostId, encryption_key: [u8; 32]) -> Self { + pub(crate) fn new(store: SqliteStore, host_id: HostId, encryption_key: [u8; 32]) -> Self { HistoryStore { store, host_id, @@ -175,7 +175,7 @@ impl HistoryStore { Ok(()) } - pub async fn delete(&self, id: HistoryId) -> Result<(RecordId, RecordIdx)> { + pub(crate) async fn delete(&self, id: HistoryId) -> Result<(RecordId, RecordIdx)> { let record = HistoryRecord::Delete(id); self.push_record(record).await @@ -183,7 +183,7 @@ impl HistoryStore { /// Delete a batch of history entries via the record store. /// Returns the record IDs so the caller can run incremental_build when ready. - pub async fn delete_entries( + pub(crate) async fn delete_entries( &self, entries: impl IntoIterator<Item = History>, ) -> Result<Vec<RecordId>> { @@ -195,7 +195,7 @@ impl HistoryStore { Ok(record_ids) } - pub async fn push(&self, history: History) -> Result<(RecordId, RecordIdx)> { + pub(crate) async fn push(&self, history: History) -> Result<(RecordId, RecordIdx)> { // TODO(ellie): move the history store to its own file // it's tiny rn so fine as is let record = HistoryRecord::Create(history); @@ -203,7 +203,7 @@ impl HistoryStore { self.push_record(record).await } - pub async fn history(&self) -> Result<Vec<HistoryRecord>> { + pub(crate) async fn history(&self) -> Result<Vec<HistoryRecord>> { // Atm this loads all history into memory // Not ideal as that is potentially quite a lot, although history will be small. let records = self.store.all_tagged(HISTORY_TAG).await?; @@ -226,7 +226,7 @@ impl HistoryStore { Ok(ret) } - pub async fn build(&self, database: &dyn Database) -> Result<()> { + pub(crate) async fn build(&self, database: &dyn Database) -> Result<()> { // I'd like to change how we rebuild and not couple this with the database, but need to // consider the structure more deeply. This will be easy to change. @@ -258,7 +258,7 @@ impl HistoryStore { Ok(()) } - pub async fn incremental_build(&self, database: &dyn Database, ids: &[RecordId]) -> Result<()> { + pub(crate) async fn incremental_build(&self, database: &dyn Database, ids: &[RecordId]) -> Result<()> { for id in ids { let record = self.store.get(*id).await; @@ -299,7 +299,7 @@ impl HistoryStore { /// Get a list of history IDs that exist in the store /// Note: This currently involves loading all history into memory. This is not going to be a /// large amount in absolute terms, but do not all it in a hot loop. - pub async fn history_ids(&self) -> Result<HashSet<HistoryId>> { + pub(crate) async fn history_ids(&self) -> Result<HashSet<HistoryId>> { let history = self.history().await?; let ret = HashSet::from_iter(history.iter().map(|h| match h { @@ -310,7 +310,7 @@ impl HistoryStore { Ok(ret) } - pub async fn init_store(&self, db: &impl Database) -> Result<()> { + pub(crate) async fn init_store(&self, db: &impl Database) -> Result<()> { let pb = ProgressBar::new_spinner(); pb.set_style( ProgressStyle::with_template("{spinner:.blue} {msg}") diff --git a/crates/turtle/src/atuin_client/import/bash.rs b/crates/turtle/src/atuin_client/import/bash.rs index d92fdfa0..e35634e7 100644 --- a/crates/turtle/src/atuin_client/import/bash.rs +++ b/crates/turtle/src/atuin_client/import/bash.rs @@ -12,7 +12,7 @@ use crate::atuin_client::history::History; use crate::atuin_client::import::read_to_end; #[derive(Debug)] -pub struct Bash { +pub(crate) struct Bash { bytes: Vec<u8>, } diff --git a/crates/turtle/src/atuin_client/import/fish.rs b/crates/turtle/src/atuin_client/import/fish.rs index 1375bdd6..edc2d437 100644 --- a/crates/turtle/src/atuin_client/import/fish.rs +++ b/crates/turtle/src/atuin_client/import/fish.rs @@ -13,7 +13,7 @@ use crate::atuin_client::history::History; use crate::atuin_client::import::read_to_end; #[derive(Debug)] -pub struct Fish { +pub(crate) struct Fish { bytes: Vec<u8>, } diff --git a/crates/turtle/src/atuin_client/import/mod.rs b/crates/turtle/src/atuin_client/import/mod.rs index 7726ead7..81e01991 100644 --- a/crates/turtle/src/atuin_client/import/mod.rs +++ b/crates/turtle/src/atuin_client/import/mod.rs @@ -8,20 +8,20 @@ use memchr::Memchr; use crate::atuin_client::history::History; -pub mod bash; -pub mod fish; -pub mod nu; -pub mod nu_histdb; -pub mod powershell; -pub mod replxx; -pub mod resh; -pub mod xonsh; -pub mod xonsh_sqlite; -pub mod zsh; -pub mod zsh_histdb; +pub(crate) mod bash; +pub(crate) mod fish; +pub(crate) mod nu; +pub(crate) mod nu_histdb; +pub(crate) mod powershell; +pub(crate) mod replxx; +pub(crate) mod resh; +pub(crate) mod xonsh; +pub(crate) mod xonsh_sqlite; +pub(crate) mod zsh; +pub(crate) mod zsh_histdb; #[async_trait] -pub trait Importer: Sized { +pub(crate) trait Importer: Sized { const NAME: &'static str; async fn new() -> Result<Self>; async fn entries(&mut self) -> Result<usize>; @@ -29,7 +29,7 @@ pub trait Importer: Sized { } #[async_trait] -pub trait Loader: Sync + Send { +pub(crate) trait Loader: Sync + Send { async fn push(&mut self, hist: History) -> eyre::Result<()>; } @@ -126,8 +126,8 @@ mod tests { use super::*; #[derive(Default)] - pub struct TestLoader { - pub buf: Vec<History>, + pub(crate) struct TestLoader { + pub(crate) buf: Vec<History>, } #[async_trait] diff --git a/crates/turtle/src/atuin_client/import/nu.rs b/crates/turtle/src/atuin_client/import/nu.rs index c93789b8..1897a969 100644 --- a/crates/turtle/src/atuin_client/import/nu.rs +++ b/crates/turtle/src/atuin_client/import/nu.rs @@ -13,7 +13,7 @@ use crate::atuin_client::history::History; use crate::atuin_client::import::read_to_end; #[derive(Debug)] -pub struct Nu { +pub(crate) struct Nu { bytes: Vec<u8>, } diff --git a/crates/turtle/src/atuin_client/import/nu_histdb.rs b/crates/turtle/src/atuin_client/import/nu_histdb.rs index 7de18369..1f66ea38 100644 --- a/crates/turtle/src/atuin_client/import/nu_histdb.rs +++ b/crates/turtle/src/atuin_client/import/nu_histdb.rs @@ -14,16 +14,16 @@ use crate::atuin_client::history::History; use crate::atuin_client::import::Loader; #[derive(sqlx::FromRow, Debug)] -pub struct HistDbEntry { - pub id: i64, - pub command_line: Vec<u8>, - pub start_timestamp: i64, - pub session_id: i64, - pub hostname: Vec<u8>, - pub cwd: Vec<u8>, - pub duration_ms: i64, - pub exit_status: i64, - pub more_info: Vec<u8>, +pub(crate) struct HistDbEntry { + pub(crate) id: i64, + pub(crate) command_line: Vec<u8>, + pub(crate) start_timestamp: i64, + pub(crate) session_id: i64, + pub(crate) hostname: Vec<u8>, + pub(crate) cwd: Vec<u8>, + pub(crate) duration_ms: i64, + pub(crate) exit_status: i64, + pub(crate) more_info: Vec<u8>, } impl From<HistDbEntry> for History { @@ -47,7 +47,7 @@ impl From<HistDbEntry> for History { } #[derive(Debug)] -pub struct NuHistDb { +pub(crate) struct NuHistDb { histdb: Vec<HistDbEntry>, } @@ -72,7 +72,7 @@ async fn hist_from_db_conn(pool: Pool<sqlx::Sqlite>) -> Result<Vec<HistDbEntry>> } impl NuHistDb { - pub fn histpath() -> Result<PathBuf> { + pub(crate) fn histpath() -> Result<PathBuf> { let base = BaseDirs::new().ok_or_else(|| eyre!("could not determine data directory"))?; let config_dir = base.config_dir().join("nushell"); diff --git a/crates/turtle/src/atuin_client/import/powershell.rs b/crates/turtle/src/atuin_client/import/powershell.rs index 8adcc850..09da0825 100644 --- a/crates/turtle/src/atuin_client/import/powershell.rs +++ b/crates/turtle/src/atuin_client/import/powershell.rs @@ -9,7 +9,7 @@ use crate::atuin_client::history::History; use crate::atuin_client::import::read_to_end; #[derive(Debug)] -pub struct PowerShell { +pub(crate) struct PowerShell { bytes: Vec<u8>, line_count: Option<usize>, } diff --git a/crates/turtle/src/atuin_client/import/replxx.rs b/crates/turtle/src/atuin_client/import/replxx.rs index 42f84df5..fbce2598 100644 --- a/crates/turtle/src/atuin_client/import/replxx.rs +++ b/crates/turtle/src/atuin_client/import/replxx.rs @@ -10,7 +10,7 @@ use crate::atuin_client::history::History; use crate::atuin_client::import::read_to_end; #[derive(Debug)] -pub struct Replxx { +pub(crate) struct Replxx { bytes: Vec<u8>, } diff --git a/crates/turtle/src/atuin_client/import/resh.rs b/crates/turtle/src/atuin_client/import/resh.rs index c5980c44..2c75e387 100644 --- a/crates/turtle/src/atuin_client/import/resh.rs +++ b/crates/turtle/src/atuin_client/import/resh.rs @@ -14,62 +14,62 @@ use crate::atuin_client::import::read_to_end; #[derive(Deserialize, Debug)] #[serde(rename_all = "camelCase")] -pub struct ReshEntry { - pub cmd_line: String, - pub exit_code: i64, - pub shell: String, - pub uname: String, - pub session_id: String, - pub home: String, - pub lang: String, - pub lc_all: String, - pub login: String, - pub pwd: String, - pub pwd_after: String, - pub shell_env: String, - pub term: String, - pub real_pwd: String, - pub real_pwd_after: String, - pub pid: i64, - pub session_pid: i64, - pub host: String, - pub hosttype: String, - pub ostype: String, - pub machtype: String, - pub shlvl: i64, - pub timezone_before: String, - pub timezone_after: String, - pub realtime_before: f64, - pub realtime_after: f64, - pub realtime_before_local: f64, - pub realtime_after_local: f64, - pub realtime_duration: f64, - pub realtime_since_session_start: f64, - pub realtime_since_boot: f64, - pub git_dir: String, - pub git_real_dir: String, - pub git_origin_remote: String, - pub git_dir_after: String, - pub git_real_dir_after: String, - pub git_origin_remote_after: String, - pub machine_id: String, - pub os_release_id: String, - pub os_release_version_id: String, - pub os_release_id_like: String, - pub os_release_name: String, - pub os_release_pretty_name: String, - pub resh_uuid: String, - pub resh_version: String, - pub resh_revision: String, - pub parts_merged: bool, - pub recalled: bool, - pub recall_last_cmd_line: String, - pub cols: String, - pub lines: String, +pub(crate) struct ReshEntry { + pub(crate) cmd_line: String, + pub(crate) exit_code: i64, + pub(crate) shell: String, + pub(crate) uname: String, + pub(crate) session_id: String, + pub(crate) home: String, + pub(crate) lang: String, + pub(crate) lc_all: String, + pub(crate) login: String, + pub(crate) pwd: String, + pub(crate) pwd_after: String, + pub(crate) shell_env: String, + pub(crate) term: String, + pub(crate) real_pwd: String, + pub(crate) real_pwd_after: String, + pub(crate) pid: i64, + pub(crate) session_pid: i64, + pub(crate) host: String, + pub(crate) hosttype: String, + pub(crate) ostype: String, + pub(crate) machtype: String, + pub(crate) shlvl: i64, + pub(crate) timezone_before: String, + pub(crate) timezone_after: String, + pub(crate) realtime_before: f64, + pub(crate) realtime_after: f64, + pub(crate) realtime_before_local: f64, + pub(crate) realtime_after_local: f64, + pub(crate) realtime_duration: f64, + pub(crate) realtime_since_session_start: f64, + pub(crate) realtime_since_boot: f64, + pub(crate) git_dir: String, + pub(crate) git_real_dir: String, + pub(crate) git_origin_remote: String, + pub(crate) git_dir_after: String, + pub(crate) git_real_dir_after: String, + pub(crate) git_origin_remote_after: String, + pub(crate) machine_id: String, + pub(crate) os_release_id: String, + pub(crate) os_release_version_id: String, + pub(crate) os_release_id_like: String, + pub(crate) os_release_name: String, + pub(crate) os_release_pretty_name: String, + pub(crate) resh_uuid: String, + pub(crate) resh_version: String, + pub(crate) resh_revision: String, + pub(crate) parts_merged: bool, + pub(crate) recalled: bool, + pub(crate) recall_last_cmd_line: String, + pub(crate) cols: String, + pub(crate) lines: String, } #[derive(Debug)] -pub struct Resh { +pub(crate) struct Resh { bytes: Vec<u8>, } diff --git a/crates/turtle/src/atuin_client/import/xonsh.rs b/crates/turtle/src/atuin_client/import/xonsh.rs index a7217826..5df24284 100644 --- a/crates/turtle/src/atuin_client/import/xonsh.rs +++ b/crates/turtle/src/atuin_client/import/xonsh.rs @@ -36,7 +36,7 @@ struct HistoryCmd { } #[derive(Debug)] -pub struct Xonsh { +pub(crate) struct Xonsh { // history is stored as a bunch of json files, one per session sessions: Vec<HistoryData>, hostname: String, diff --git a/crates/turtle/src/atuin_client/import/xonsh_sqlite.rs b/crates/turtle/src/atuin_client/import/xonsh_sqlite.rs index ceedf7e9..326fe74b 100644 --- a/crates/turtle/src/atuin_client/import/xonsh_sqlite.rs +++ b/crates/turtle/src/atuin_client/import/xonsh_sqlite.rs @@ -81,7 +81,7 @@ fn xonsh_db_path(xonsh_data_dir: Option<String>) -> Result<PathBuf> { } #[derive(Debug)] -pub struct XonshSqlite { +pub(crate) struct XonshSqlite { pool: SqlitePool, hostname: String, } diff --git a/crates/turtle/src/atuin_client/import/zsh.rs b/crates/turtle/src/atuin_client/import/zsh.rs index e1fd813a..55d082d3 100644 --- a/crates/turtle/src/atuin_client/import/zsh.rs +++ b/crates/turtle/src/atuin_client/import/zsh.rs @@ -14,7 +14,7 @@ use crate::atuin_client::history::History; use crate::atuin_client::import::read_to_end; #[derive(Debug)] -pub struct Zsh { +pub(crate) struct Zsh { bytes: Vec<u8>, } diff --git a/crates/turtle/src/atuin_client/import/zsh_histdb.rs b/crates/turtle/src/atuin_client/import/zsh_histdb.rs index f61bb74f..46622e32 100644 --- a/crates/turtle/src/atuin_client/import/zsh_histdb.rs +++ b/crates/turtle/src/atuin_client/import/zsh_histdb.rs @@ -48,24 +48,24 @@ use crate::atuin_client::import::Loader; use crate::atuin_client::utils::{get_hostname, get_username}; #[derive(sqlx::FromRow, Debug)] -pub struct HistDbEntryCount { - pub count: usize, +pub(crate) struct HistDbEntryCount { + pub(crate) count: usize, } #[derive(sqlx::FromRow, Debug)] -pub struct HistDbEntry { - pub id: i64, - pub start_time: PrimitiveDateTime, - pub host: Vec<u8>, - pub dir: Vec<u8>, - pub argv: Vec<u8>, - pub duration: i64, - pub exit_status: i64, - pub session: i64, +pub(crate) struct HistDbEntry { + pub(crate) id: i64, + pub(crate) start_time: PrimitiveDateTime, + pub(crate) host: Vec<u8>, + pub(crate) dir: Vec<u8>, + pub(crate) argv: Vec<u8>, + pub(crate) duration: i64, + pub(crate) exit_status: i64, + pub(crate) session: i64, } #[derive(Debug)] -pub struct ZshHistDb { +pub(crate) struct ZshHistDb { histdb: Vec<HistDbEntry>, username: String, } @@ -93,7 +93,7 @@ async fn hist_from_db_conn(pool: Pool<sqlx::Sqlite>) -> Result<Vec<HistDbEntry>> } impl ZshHistDb { - pub fn histpath_candidate() -> PathBuf { + pub(crate) fn histpath_candidate() -> PathBuf { // By default histdb database is `${HOME}/.histdb/zsh-history.db` // This can be modified by ${HISTDB_FILE} // @@ -106,7 +106,7 @@ impl ZshHistDb { .map(|x| Path::new(x).to_path_buf()) .unwrap_or_else(|_err| home_dir.join(".histdb/zsh-history.db")) } - pub fn histpath() -> Result<PathBuf> { + pub(crate) fn histpath() -> Result<PathBuf> { let histdb_path = ZshHistDb::histpath_candidate(); if histdb_path.exists() { Ok(histdb_path) diff --git a/crates/turtle/src/atuin_client/login.rs b/crates/turtle/src/atuin_client/login.rs index ca4e16fe..91876744 100644 --- a/crates/turtle/src/atuin_client/login.rs +++ b/crates/turtle/src/atuin_client/login.rs @@ -12,7 +12,7 @@ use crate::atuin_client::{ settings::Settings, }; -pub async fn login( +pub(crate) async fn login( settings: &Settings, store: &SqliteStore, username: String, diff --git a/crates/turtle/src/atuin_client/logout.rs b/crates/turtle/src/atuin_client/logout.rs index 343934b9..2ec41e40 100644 --- a/crates/turtle/src/atuin_client/logout.rs +++ b/crates/turtle/src/atuin_client/logout.rs @@ -2,7 +2,7 @@ use eyre::Result; use crate::atuin_client::settings::Settings; -pub async fn logout() -> Result<()> { +pub(crate) async fn logout() -> Result<()> { let meta = Settings::meta_store().await?; if meta.logged_in().await? { diff --git a/crates/turtle/src/atuin_client/meta.rs b/crates/turtle/src/atuin_client/meta.rs index 2fbfe275..502d7421 100644 --- a/crates/turtle/src/atuin_client/meta.rs +++ b/crates/turtle/src/atuin_client/meta.rs @@ -24,13 +24,13 @@ const KEY_LATEST_VERSION: &str = "latest_version"; const KEY_SESSION: &str = "session"; const KEY_FILES_MIGRATED: &str = "files_migrated"; -pub struct MetaStore { +pub(crate) struct MetaStore { pool: SqlitePool, cached_host_id: OnceCell<HostId>, } impl MetaStore { - pub async fn new(path: impl AsRef<Path>, timeout: f64) -> Result<Self> { + pub(crate) async fn new(path: impl AsRef<Path>, timeout: f64) -> Result<Self> { let path = path.as_ref(); let path_str = path .as_os_str() @@ -86,7 +86,7 @@ impl MetaStore { // Generic key-value operations - pub async fn get(&self, key: &str) -> Result<Option<String>> { + pub(crate) async fn get(&self, key: &str) -> Result<Option<String>> { let row: Option<(String,)> = sqlx::query_as("SELECT value FROM meta WHERE key = ?1") .bind(key) .fetch_optional(&self.pool) @@ -95,7 +95,7 @@ impl MetaStore { Ok(row.map(|r| r.0)) } - pub async fn set(&self, key: &str, value: &str) -> Result<()> { + pub(crate) async fn set(&self, key: &str, value: &str) -> Result<()> { sqlx::query( "INSERT INTO meta (key, value, updated_at) VALUES (?1, ?2, strftime('%s', 'now')) ON CONFLICT(key) DO UPDATE SET value = ?2, updated_at = strftime('%s', 'now')", @@ -108,7 +108,7 @@ impl MetaStore { Ok(()) } - pub async fn delete(&self, key: &str) -> Result<()> { + pub(crate) async fn delete(&self, key: &str) -> Result<()> { sqlx::query("DELETE FROM meta WHERE key = ?1") .bind(key) .execute(&self.pool) @@ -119,7 +119,7 @@ impl MetaStore { // Typed accessors - pub async fn host_id(&self) -> Result<HostId> { + pub(crate) async fn host_id(&self) -> Result<HostId> { self.cached_host_id .get_or_try_init(|| async { if let Some(id) = self.get(KEY_HOST_ID).await? { @@ -138,14 +138,14 @@ impl MetaStore { .copied() } - pub async fn last_sync(&self) -> Result<OffsetDateTime> { + pub(crate) async fn last_sync(&self) -> Result<OffsetDateTime> { match self.get(KEY_LAST_SYNC).await? { Some(v) => Ok(OffsetDateTime::parse(v.as_str(), &Rfc3339)?), None => Ok(OffsetDateTime::UNIX_EPOCH), } } - pub async fn save_sync_time(&self) -> Result<()> { + pub(crate) async fn save_sync_time(&self) -> Result<()> { self.set( KEY_LAST_SYNC, OffsetDateTime::now_utc().format(&Rfc3339)?.as_str(), @@ -153,14 +153,14 @@ impl MetaStore { .await } - pub async fn last_version_check(&self) -> Result<OffsetDateTime> { + pub(crate) async fn last_version_check(&self) -> Result<OffsetDateTime> { match self.get(KEY_LAST_VERSION_CHECK).await? { Some(v) => Ok(OffsetDateTime::parse(v.as_str(), &Rfc3339)?), None => Ok(OffsetDateTime::UNIX_EPOCH), } } - pub async fn save_version_check_time(&self) -> Result<()> { + pub(crate) async fn save_version_check_time(&self) -> Result<()> { self.set( KEY_LAST_VERSION_CHECK, OffsetDateTime::now_utc().format(&Rfc3339)?.as_str(), @@ -168,27 +168,27 @@ impl MetaStore { .await } - pub async fn latest_version(&self) -> Result<Option<String>> { + pub(crate) async fn latest_version(&self) -> Result<Option<String>> { self.get(KEY_LATEST_VERSION).await } - pub async fn save_latest_version(&self, version: &str) -> Result<()> { + pub(crate) async fn save_latest_version(&self, version: &str) -> Result<()> { self.set(KEY_LATEST_VERSION, version).await } - pub async fn session_token(&self) -> Result<Option<String>> { + pub(crate) async fn session_token(&self) -> Result<Option<String>> { self.get(KEY_SESSION).await } - pub async fn save_session(&self, token: &str) -> Result<()> { + pub(crate) async fn save_session(&self, token: &str) -> Result<()> { self.set(KEY_SESSION, token).await } - pub async fn delete_session(&self) -> Result<()> { + pub(crate) async fn delete_session(&self) -> Result<()> { self.delete(KEY_SESSION).await } - pub async fn logged_in(&self) -> Result<bool> { + pub(crate) async fn logged_in(&self) -> Result<bool> { Ok(self.session_token().await?.is_some()) } diff --git a/crates/turtle/src/atuin_client/mod.rs b/crates/turtle/src/atuin_client/mod.rs index 7f07f2e2..0ac294cf 100644 --- a/crates/turtle/src/atuin_client/mod.rs +++ b/crates/turtle/src/atuin_client/mod.rs @@ -1,26 +1,26 @@ #[cfg(feature = "sync")] -pub mod api_client; +pub(crate) mod api_client; #[cfg(feature = "sync")] -pub mod auth; +pub(crate) mod auth; #[cfg(feature = "sync")] -pub mod login; +pub(crate) mod login; #[cfg(feature = "sync")] -pub mod register; +pub(crate) mod register; #[cfg(feature = "sync")] -pub mod sync; +pub(crate) mod sync; -pub mod database; -pub mod distro; -pub mod encryption; -pub mod history; -pub mod import; -pub mod logout; -pub mod meta; -pub mod ordering; -pub mod plugin; -pub mod record; -pub mod secrets; -pub mod settings; -pub mod theme; +pub(crate) mod database; +pub(crate) mod distro; +pub(crate) mod encryption; +pub(crate) mod history; +pub(crate) mod import; +pub(crate) mod logout; +pub(crate) mod meta; +pub(crate) mod ordering; +pub(crate) mod plugin; +pub(crate) mod record; +pub(crate) mod secrets; +pub(crate) mod settings; +pub(crate) mod theme; mod utils; diff --git a/crates/turtle/src/atuin_client/ordering.rs b/crates/turtle/src/atuin_client/ordering.rs index 4e5ec84c..446a5dac 100644 --- a/crates/turtle/src/atuin_client/ordering.rs +++ b/crates/turtle/src/atuin_client/ordering.rs @@ -2,7 +2,7 @@ use minspan::minspan; use super::{history::History, settings::SearchMode}; -pub fn reorder_fuzzy(mode: SearchMode, query: &str, res: Vec<History>) -> Vec<History> { +pub(crate) fn reorder_fuzzy(mode: SearchMode, query: &str, res: Vec<History>) -> Vec<History> { match mode { SearchMode::Fuzzy => reorder(query, |x| &x.command, res), _ => res, diff --git a/crates/turtle/src/atuin_client/plugin.rs b/crates/turtle/src/atuin_client/plugin.rs index 6f351bf1..e97b1dbf 100644 --- a/crates/turtle/src/atuin_client/plugin.rs +++ b/crates/turtle/src/atuin_client/plugin.rs @@ -1,14 +1,14 @@ use std::collections::HashMap; #[derive(Debug, Clone)] -pub struct OfficialPlugin { - pub name: String, - pub description: String, - pub install_message: String, +pub(crate) struct OfficialPlugin { + pub(crate) name: String, + pub(crate) description: String, + pub(crate) install_message: String, } impl OfficialPlugin { - pub fn new(name: &str, description: &str, install_message: &str) -> Self { + pub(crate) fn new(name: &str, description: &str, install_message: &str) -> Self { Self { name: name.to_string(), description: description.to_string(), @@ -17,12 +17,12 @@ impl OfficialPlugin { } } -pub struct OfficialPluginRegistry { +pub(crate) struct OfficialPluginRegistry { plugins: HashMap<String, OfficialPlugin>, } impl OfficialPluginRegistry { - pub fn new() -> Self { + pub(crate) fn new() -> Self { let mut registry = Self { plugins: HashMap::new(), }; @@ -47,15 +47,15 @@ impl OfficialPluginRegistry { ); } - pub fn get_plugin(&self, name: &str) -> Option<&OfficialPlugin> { + pub(crate) fn get_plugin(&self, name: &str) -> Option<&OfficialPlugin> { self.plugins.get(name) } - pub fn is_official_plugin(&self, name: &str) -> bool { + pub(crate) fn is_official_plugin(&self, name: &str) -> bool { self.plugins.contains_key(name) } - pub fn get_install_message(&self, name: &str) -> Option<&str> { + pub(crate) fn get_install_message(&self, name: &str) -> Option<&str> { self.plugins .get(name) .map(|plugin| plugin.install_message.as_str()) @@ -68,13 +68,13 @@ impl Default for OfficialPluginRegistry { } } -pub struct PluginContext { +pub(crate) struct PluginContext { #[cfg(windows)] _update_on_windows: Option<UpdateOnWindowsContext>, } impl PluginContext { - pub fn new(_subcommand: &str) -> Self { + pub(crate) fn new(_subcommand: &str) -> Self { PluginContext { #[cfg(windows)] _update_on_windows: (_subcommand == "update").then(UpdateOnWindowsContext::new), @@ -95,7 +95,7 @@ struct UpdateOnWindowsContext { impl UpdateOnWindowsContext { const OLD_FILE_NAME: &'static str = "atuin.old"; - pub fn new() -> Self { + pub(crate) fn new() -> Self { // Windows doesn't let you overwrite a running exe, but it lets you rename it, // so make some room for atuin-update to install the new version. let initial_exe = std::env::current_exe().ok().and_then(|exe| { diff --git a/crates/turtle/src/atuin_client/record/encryption.rs b/crates/turtle/src/atuin_client/record/encryption.rs index 22dcdec3..dabd0fa7 100644 --- a/crates/turtle/src/atuin_client/record/encryption.rs +++ b/crates/turtle/src/atuin_client/record/encryption.rs @@ -11,7 +11,7 @@ use serde::{Deserialize, Serialize}; /// Use PASETO V4 Local encryption using the additional data as an implicit assertion. #[expect(non_camel_case_types)] -pub struct PASETO_V4; +pub(crate) struct PASETO_V4; /* Why do we use a random content-encryption key? diff --git a/crates/turtle/src/atuin_client/record/mod.rs b/crates/turtle/src/atuin_client/record/mod.rs index c40fd395..175c7a9d 100644 --- a/crates/turtle/src/atuin_client/record/mod.rs +++ b/crates/turtle/src/atuin_client/record/mod.rs @@ -1,6 +1,6 @@ -pub mod encryption; -pub mod sqlite_store; -pub mod store; +pub(crate) mod encryption; +pub(crate) mod sqlite_store; +pub(crate) mod store; #[cfg(feature = "sync")] -pub mod sync; +pub(crate) mod sync; diff --git a/crates/turtle/src/atuin_client/record/sqlite_store.rs b/crates/turtle/src/atuin_client/record/sqlite_store.rs index 03f82d13..f8eab076 100644 --- a/crates/turtle/src/atuin_client/record/sqlite_store.rs +++ b/crates/turtle/src/atuin_client/record/sqlite_store.rs @@ -25,12 +25,12 @@ use super::encryption::PASETO_V4; use super::store::Store; #[derive(Debug, Clone)] -pub struct SqliteStore { +pub(crate) struct SqliteStore { pool: SqlitePool, } impl SqliteStore { - pub async fn new(path: impl AsRef<Path>, timeout: f64) -> Result<Self> { + pub(crate) async fn new(path: impl AsRef<Path>, timeout: f64) -> Result<Self> { let path = path.as_ref(); debug!("opening sqlite database at {path:?}"); diff --git a/crates/turtle/src/atuin_client/record/store.rs b/crates/turtle/src/atuin_client/record/store.rs index f99085d0..db832a0d 100644 --- a/crates/turtle/src/atuin_client/record/store.rs +++ b/crates/turtle/src/atuin_client/record/store.rs @@ -8,7 +8,7 @@ use crate::atuin_common::record::{EncryptedData, HostId, Record, RecordId, Recor /// As is, the record store is intended as the source of truth for arbitrary data, which could /// be shell history, kvs, etc. #[async_trait] -pub trait Store { +pub(crate) trait Store { // Push a record async fn push(&self, record: &Record<EncryptedData>) -> Result<()> { self.push_batch(std::iter::once(record)).await diff --git a/crates/turtle/src/atuin_client/record/sync.rs b/crates/turtle/src/atuin_client/record/sync.rs index f831570b..36eaec91 100644 --- a/crates/turtle/src/atuin_client/record/sync.rs +++ b/crates/turtle/src/atuin_client/record/sync.rs @@ -12,7 +12,7 @@ use crate::atuin_common::record::{Diff, HostId, RecordId, RecordIdx, RecordStatu use indicatif::{ProgressBar, ProgressState, ProgressStyle}; #[derive(Error, Debug)] -pub enum SyncError { +pub(crate) enum SyncError { #[error("the local store is ahead of the remote, but for another host. has remote lost data?")] LocalAheadOtherHost, @@ -38,7 +38,7 @@ pub enum SyncError { } #[derive(Debug, Eq, PartialEq)] -pub enum Operation { +pub(crate) enum Operation { // Either upload or download until the states matches the below Upload { local: RecordIdx, @@ -58,7 +58,7 @@ pub enum Operation { }, } -pub async fn build_client(settings: &Settings) -> Result<Client<'_>, SyncError> { +pub(crate) async fn build_client(settings: &Settings) -> Result<Client<'_>, SyncError> { Client::new( &settings.sync_address, settings @@ -71,7 +71,7 @@ pub async fn build_client(settings: &Settings) -> Result<Client<'_>, SyncError> .map_err(|e| SyncError::OperationalError { msg: e.to_string() }) } -pub async fn diff( +pub(crate) async fn diff( client: &Client<'_>, store: &impl Store, ) -> Result<(Vec<Diff>, RecordStatus), SyncError> { @@ -94,7 +94,7 @@ pub async fn diff( // With the store as context, we can determine if a tail exists locally or not and therefore if it needs uploading or download. // In theory this could be done as a part of the diffing stage, but it's easier to reason // about and test this way -pub async fn operations( +pub(crate) async fn operations( diffs: Vec<Diff>, _store: &impl Store, ) -> Result<Vec<Operation>, SyncError> { @@ -283,7 +283,7 @@ async fn sync_download( Ok(ret) } -pub async fn sync_remote( +pub(crate) async fn sync_remote( client: &Client<'_>, operations: Vec<Operation>, local_store: &impl Store, @@ -323,7 +323,7 @@ pub async fn sync_remote( Ok((uploaded, downloaded)) } -pub async fn check_encryption_key( +pub(crate) async fn check_encryption_key( client: &Client<'_>, remote_index: &RecordStatus, encryption_key: &[u8; 32], @@ -354,7 +354,7 @@ pub async fn check_encryption_key( Ok(()) } -pub async fn sync( +pub(crate) async fn sync( settings: &Settings, store: &impl Store, encryption_key: &[u8; 32], diff --git a/crates/turtle/src/atuin_client/register.rs b/crates/turtle/src/atuin_client/register.rs index 4b14c233..1c78b6bc 100644 --- a/crates/turtle/src/atuin_client/register.rs +++ b/crates/turtle/src/atuin_client/register.rs @@ -2,7 +2,7 @@ use eyre::Result; use crate::atuin_client::{api_client, settings::Settings}; -pub async fn register_classic( +pub(crate) async fn register_classic( settings: &Settings, username: String, email: String, diff --git a/crates/turtle/src/atuin_client/secrets.rs b/crates/turtle/src/atuin_client/secrets.rs index e8a6ab62..09058071 100644 --- a/crates/turtle/src/atuin_client/secrets.rs +++ b/crates/turtle/src/atuin_client/secrets.rs @@ -3,13 +3,13 @@ use regex::RegexSet; use std::sync::LazyLock; -pub enum TestValue<'a> { +pub(crate) enum TestValue<'a> { Single(&'a str), Multiple(&'a [&'a str]), } /// A list of `(name, regex, test)`, where `test` should match against `regex`. -pub static SECRET_PATTERNS: &[(&str, &str, TestValue)] = &[ +pub(crate) static SECRET_PATTERNS: &[(&str, &str, TestValue)] = &[ ( "AWS Access Key ID", "A[KS]IA[0-9A-Z]{16}", @@ -135,7 +135,7 @@ pub static SECRET_PATTERNS: &[(&str, &str, TestValue)] = &[ ]; /// The `regex` expressions from [`SECRET_PATTERNS`] compiled into a `RegexSet`. -pub static SECRET_PATTERNS_RE: LazyLock<RegexSet> = LazyLock::new(|| { +pub(crate) static SECRET_PATTERNS_RE: LazyLock<RegexSet> = LazyLock::new(|| { let exprs = SECRET_PATTERNS.iter().map(|f| f.1); RegexSet::new(exprs).expect("Failed to build secrets regex") }); diff --git a/crates/turtle/src/atuin_client/settings.rs b/crates/turtle/src/atuin_client/settings.rs index b0ffc7c1..046aad1a 100644 --- a/crates/turtle/src/atuin_client/settings.rs +++ b/crates/turtle/src/atuin_client/settings.rs @@ -15,20 +15,20 @@ use serde::{Deserialize, Serialize}; use serde_with::DeserializeFromStr; use time::{OffsetDateTime, UtcOffset, format_description::FormatItem, macros::format_description}; -pub const HISTORY_PAGE_SIZE: i64 = 100; +pub(crate) const HISTORY_PAGE_SIZE: i64 = 100; static DATA_DIR: OnceLock<PathBuf> = OnceLock::new(); static META_CONFIG: OnceLock<(String, f64)> = OnceLock::new(); static META_STORE: OnceCell<crate::atuin_client::meta::MetaStore> = OnceCell::const_new(); pub(crate) mod meta; -pub mod watcher; +pub(crate) mod watcher; /// Default sync address for Atuin's hosted service -pub const DEFAULT_SYNC_ADDRESS: &str = "https://api.atuin.sh"; +pub(crate) const DEFAULT_SYNC_ADDRESS: &str = "https://api.atuin.sh"; #[derive(Clone, Debug, Deserialize, Copy, ValueEnum, PartialEq, Serialize)] -pub enum SearchMode { +pub(crate) enum SearchMode { #[serde(rename = "prefix")] Prefix, @@ -48,7 +48,7 @@ pub enum SearchMode { } impl SearchMode { - pub fn as_str(&self) -> &'static str { + pub(crate) fn as_str(&self) -> &'static str { match self { SearchMode::Prefix => "PREFIX", SearchMode::FullText => "FULLTXT", @@ -57,7 +57,7 @@ impl SearchMode { SearchMode::DaemonFuzzy => "DAEMON", } } - pub fn next(&self, settings: &Settings) -> Self { + pub(crate) fn next(&self, settings: &Settings) -> Self { match self { SearchMode::Prefix => SearchMode::FullText, // if the user is using skim, we go to skim @@ -74,7 +74,7 @@ impl SearchMode { } #[derive(Clone, Debug, Deserialize, Copy, PartialEq, Eq, ValueEnum, Serialize)] -pub enum FilterMode { +pub(crate) enum FilterMode { #[serde(rename = "global")] Global = 0, @@ -95,7 +95,7 @@ pub enum FilterMode { } impl FilterMode { - pub fn as_str(&self) -> &'static str { + pub(crate) fn as_str(&self) -> &'static str { match self { FilterMode::Global => "GLOBAL", FilterMode::Host => "HOST", @@ -108,7 +108,7 @@ impl FilterMode { } #[derive(Clone, Debug, Deserialize, Copy, Serialize)] -pub enum ExitMode { +pub(crate) enum ExitMode { #[serde(rename = "return-original")] ReturnOriginal, @@ -119,7 +119,7 @@ pub enum ExitMode { // FIXME: Can use upstream Dialect enum if https://github.com/stevedonovan/chrono-english/pull/16 is merged // FIXME: Above PR was merged, but dependency was changed to interim (fork of chrono-english) in the ... interim #[derive(Clone, Debug, Deserialize, Copy, Serialize)] -pub enum Dialect { +pub(crate) enum Dialect { #[serde(rename = "us")] Us, @@ -143,7 +143,7 @@ impl From<Dialect> for interim::Dialect { /// /// See: <https://github.com/atuinsh/atuin/pull/1517#discussion_r1447516426> #[derive(Clone, Copy, Debug, Eq, PartialEq, DeserializeFromStr, Serialize)] -pub struct Timezone(pub UtcOffset); +pub(crate) struct Timezone(pub(crate) UtcOffset); impl fmt::Display for Timezone { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.0.fmt(f) @@ -187,7 +187,7 @@ impl FromStr for Timezone { } #[derive(Clone, Debug, Deserialize, Copy, Serialize)] -pub enum Style { +pub(crate) enum Style { #[serde(rename = "auto")] Auto, @@ -199,7 +199,7 @@ pub enum Style { } #[derive(Clone, Debug, Deserialize, Copy, Serialize)] -pub enum WordJumpMode { +pub(crate) enum WordJumpMode { #[serde(rename = "emacs")] Emacs, @@ -208,7 +208,7 @@ pub enum WordJumpMode { } #[derive(Clone, Debug, Deserialize, Copy, PartialEq, Eq, ValueEnum, Serialize)] -pub enum KeymapMode { +pub(crate) enum KeymapMode { #[serde(rename = "emacs")] Emacs, @@ -223,7 +223,7 @@ pub enum KeymapMode { } impl KeymapMode { - pub fn as_str(&self) -> &'static str { + pub(crate) fn as_str(&self) -> &'static str { match self { KeymapMode::Emacs => "EMACS", KeymapMode::VimNormal => "VIMNORMAL", @@ -239,7 +239,7 @@ impl KeymapMode { // used in HashMap (https://stackoverflow.com/questions/67142663). We instead // define an adapter type. #[derive(Clone, Debug, Deserialize, Copy, PartialEq, Eq, ValueEnum, Serialize)] -pub enum CursorStyle { +pub(crate) enum CursorStyle { #[serde(rename = "default")] DefaultUserShape, @@ -263,7 +263,7 @@ pub enum CursorStyle { } impl CursorStyle { - pub fn as_str(&self) -> &'static str { + pub(crate) fn as_str(&self) -> &'static str { match self { CursorStyle::DefaultUserShape => "DEFAULT", CursorStyle::BlinkingBlock => "BLINKBLOCK", @@ -277,13 +277,13 @@ impl CursorStyle { } #[derive(Clone, Debug, Deserialize, Serialize)] -pub struct Stats { +pub(crate) struct Stats { #[serde(default = "Stats::common_prefix_default")] - pub common_prefix: Vec<String>, // sudo, etc. commands we want to strip off + pub(crate) common_prefix: Vec<String>, // sudo, etc. commands we want to strip off #[serde(default = "Stats::common_subcommands_default")] - pub common_subcommands: Vec<String>, // kubectl, commands we should consider subcommands for + pub(crate) common_subcommands: Vec<String>, // kubectl, commands we should consider subcommands for #[serde(default = "Stats::ignored_commands_default")] - pub ignored_commands: Vec<String>, // cd, ls, etc. commands we want to completely hide from stats + pub(crate) ignored_commands: Vec<String>, // cd, ls, etc. commands we want to completely hide from stats } impl Stats { @@ -346,7 +346,7 @@ impl Default for Stats { /// (useful for local development against a Hub instance). #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, Serialize, Default)] #[serde(rename_all = "lowercase")] -pub enum SyncProtocol { +pub(crate) enum SyncProtocol { /// Use legacy CLI authentication (Token from CLI register/login) #[default] Legacy, @@ -359,7 +359,7 @@ pub enum SyncProtocol { /// the right auth header and endpoint style. #[cfg(feature = "sync")] #[derive(Debug, Clone)] -pub enum SyncAuth { +pub(crate) enum SyncAuth { /// Self-hosted Rust server. Uses `Authorization: Token <session>` and /// legacy endpoints. Legacy { token: String }, @@ -373,7 +373,7 @@ impl SyncAuth { /// Convert into the auth token type used by the API client. /// /// Returns an error with an actionable message for `NotLoggedIn`. - pub fn into_auth_token(self) -> Result<crate::atuin_client::api_client::AuthToken> { + pub(crate) fn into_auth_token(self) -> Result<crate::atuin_client::api_client::AuthToken> { use crate::atuin_client::api_client::AuthToken; match self { SyncAuth::Legacy { token } => Ok(AuthToken::Token(token)), @@ -383,19 +383,19 @@ impl SyncAuth { } #[derive(Clone, Debug, Deserialize, Default, Serialize)] -pub struct Keys { - pub scroll_exits: bool, - pub exit_past_line_start: bool, - pub accept_past_line_end: bool, - pub accept_past_line_start: bool, - pub accept_with_backspace: bool, - pub prefix: String, +pub(crate) struct Keys { + pub(crate) scroll_exits: bool, + pub(crate) exit_past_line_start: bool, + pub(crate) accept_past_line_end: bool, + pub(crate) accept_past_line_start: bool, + pub(crate) accept_with_backspace: bool, + pub(crate) prefix: String, } impl Keys { /// The standard default values for all `[keys]` options. /// These match the config defaults set in `builder_with_data_dir()`. - pub fn standard_defaults() -> Self { + pub(crate) fn standard_defaults() -> Self { Keys { scroll_exits: true, exit_past_line_start: true, @@ -407,7 +407,7 @@ impl Keys { } /// Returns true if any value differs from the standard defaults. - pub fn has_non_default_values(&self) -> bool { + pub(crate) fn has_non_default_values(&self) -> bool { let d = Self::standard_defaults(); self.scroll_exits != d.scroll_exits || self.exit_past_line_start != d.exit_past_line_start @@ -420,19 +420,19 @@ impl Keys { /// A single rule within a conditional keybinding config. #[derive(Clone, Debug, Deserialize, Serialize)] -pub struct KeyRuleConfig { +pub(crate) struct KeyRuleConfig { /// Optional condition expression (e.g. "cursor-at-start", "input-empty && no-results"). /// If absent, the rule always matches. #[serde(default)] - pub when: Option<String>, + pub(crate) when: Option<String>, /// The action to perform (e.g. "exit", "cursor-left", "accept"). - pub action: String, + pub(crate) action: String, } /// A keybinding config value: either a simple action string or an ordered list of conditional rules. #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(untagged)] -pub enum KeyBindingConfig { +pub(crate) enum KeyBindingConfig { /// Simple unconditional binding: `"ctrl-c" = "return-original"` Simple(String), /// Conditional binding: `"left" = [{ when = "cursor-at-start", action = "exit" }, { action = "cursor-left" }]` @@ -442,22 +442,22 @@ pub enum KeyBindingConfig { /// User-facing keymap configuration. Each mode maps key strings to bindings. /// Keys present here override the defaults for that key; unmentioned keys keep defaults. #[derive(Clone, Debug, Deserialize, Serialize, Default)] -pub struct KeymapConfig { +pub(crate) struct KeymapConfig { #[serde(default)] - pub emacs: HashMap<String, KeyBindingConfig>, + pub(crate) emacs: HashMap<String, KeyBindingConfig>, #[serde(default, rename = "vim-normal")] - pub vim_normal: HashMap<String, KeyBindingConfig>, + pub(crate) vim_normal: HashMap<String, KeyBindingConfig>, #[serde(default, rename = "vim-insert")] - pub vim_insert: HashMap<String, KeyBindingConfig>, + pub(crate) vim_insert: HashMap<String, KeyBindingConfig>, #[serde(default)] - pub inspector: HashMap<String, KeyBindingConfig>, + pub(crate) inspector: HashMap<String, KeyBindingConfig>, #[serde(default)] - pub prefix: HashMap<String, KeyBindingConfig>, + pub(crate) prefix: HashMap<String, KeyBindingConfig>, } impl KeymapConfig { /// Returns true if no keybinding overrides are configured in any mode. - pub fn is_empty(&self) -> bool { + pub(crate) fn is_empty(&self) -> bool { self.emacs.is_empty() && self.vim_normal.is_empty() && self.vim_insert.is_empty() @@ -467,82 +467,82 @@ impl KeymapConfig { } #[derive(Clone, Debug, Deserialize, Serialize)] -pub struct Preview { - pub strategy: PreviewStrategy, +pub(crate) struct Preview { + pub(crate) strategy: PreviewStrategy, } #[derive(Clone, Debug, Deserialize, Serialize)] -pub struct Theme { +pub(crate) struct Theme { /// Name of desired theme ("default" for base) - pub name: String, + pub(crate) name: String, /// Whether any available additional theme debug should be shown - pub debug: Option<bool>, + pub(crate) debug: Option<bool>, /// How many levels of parenthood will be traversed if needed - pub max_depth: Option<u8>, + pub(crate) max_depth: Option<u8>, } #[derive(Clone, Debug, Deserialize, Serialize)] -pub struct Daemon { +pub(crate) struct Daemon { /// Use the daemon to sync /// If enabled, history hooks are routed through the daemon. #[serde(alias = "enable")] - pub enabled: bool, + pub(crate) enabled: bool, /// Automatically start and manage a local daemon when needed. - pub autostart: bool, + pub(crate) autostart: bool, /// The daemon will handle sync on an interval. How often to sync, in seconds. - pub sync_frequency: u64, + pub(crate) sync_frequency: u64, /// The path to the unix socket used by the daemon - pub socket_path: String, + pub(crate) socket_path: String, /// Path to the daemon pidfile used for process coordination. - pub pidfile_path: String, + pub(crate) pidfile_path: String, /// Use a socket passed via systemd's socket activation protocol, instead of the path - pub systemd_socket: bool, + pub(crate) systemd_socket: bool, /// The port that should be used for TCP on non unix systems - pub tcp_port: u64, + pub(crate) tcp_port: u64, } #[derive(Clone, Debug, Deserialize, Serialize)] -pub struct Search { +pub(crate) struct Search { /// The list of enabled filter modes, in order of priority. - pub filters: Vec<FilterMode>, + pub(crate) filters: Vec<FilterMode>, /// The recency score multiplier for the search index (default: 1.0). /// Values < 1.0 reduce weight, > 1.0 increase weight, 0.0 disables. - pub recency_score_multiplier: f64, + pub(crate) recency_score_multiplier: f64, /// The frequency score multiplier for the search index (default: 1.0). /// Values < 1.0 reduce weight, > 1.0 increase weight, 0.0 disables. - pub frequency_score_multiplier: f64, + pub(crate) frequency_score_multiplier: f64, /// The overall frecency score multiplier for the search index (default: 1.0). /// Applied after combining recency and frequency scores. - pub frecency_score_multiplier: f64, + pub(crate) frecency_score_multiplier: f64, } #[derive(Clone, Debug, Deserialize, Serialize)] -pub struct Tmux { +pub(crate) struct Tmux { /// Enable using atuin with tmux popup (tmux >= 3.2) - pub enabled: bool, + pub(crate) enabled: bool, /// Width of the tmux popup (percentage) - pub width: String, + pub(crate) width: String, /// Height of the tmux popup (percentage) - pub height: String, + pub(crate) height: String, } /// Log level for file logging. Maps to tracing's LevelFilter. #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Deserialize, Serialize)] #[serde(rename_all = "lowercase")] -pub enum LogLevel { +pub(crate) enum LogLevel { Trace, Debug, #[default] @@ -553,7 +553,7 @@ pub enum LogLevel { impl LogLevel { /// Convert to a tracing directive string for use with EnvFilter. - pub fn as_directive(&self) -> &'static str { + pub(crate) fn as_directive(&self) -> &'static str { match self { LogLevel::Trace => "trace", LogLevel::Debug => "debug", @@ -566,102 +566,102 @@ impl LogLevel { /// Configuration for a specific log type (search or daemon). #[derive(Clone, Debug, Default, Deserialize, Serialize)] -pub struct LogConfig { +pub(crate) struct LogConfig { /// Log file name (relative to dir) or absolute path. - pub file: String, + pub(crate) file: String, /// Override global enabled setting for this log type. - pub enabled: Option<bool>, + pub(crate) enabled: Option<bool>, /// Override global level setting for this log type. - pub level: Option<LogLevel>, + pub(crate) level: Option<LogLevel>, /// Override global retention days setting for this log type. - pub retention: Option<u64>, + pub(crate) retention: Option<u64>, } #[derive(Clone, Debug, Deserialize, Serialize)] -pub struct Logs { +pub(crate) struct Logs { /// Enable file logging globally. Defaults to true. #[serde(default = "Logs::default_enabled")] - pub enabled: bool, + pub(crate) enabled: bool, /// Directory for log files. Defaults to ~/.atuin/logs - pub dir: String, + pub(crate) dir: String, /// Default log level for file logging. Defaults to "info". /// Note: ATUIN_LOG environment variable overrides this. #[serde(default)] - pub level: LogLevel, + pub(crate) level: LogLevel, /// Default retention days for log files. Defaults to 4. #[serde(default = "Logs::default_retention")] - pub retention: u64, + pub(crate) retention: u64, /// Search log settings #[serde(default)] - pub search: LogConfig, + pub(crate) search: LogConfig, /// Daemon log settings #[serde(default)] - pub daemon: LogConfig, + pub(crate) daemon: LogConfig, /// AI log settings #[serde(default)] - pub ai: LogConfig, + pub(crate) ai: LogConfig, } #[derive(Default, Clone, Debug, Deserialize, Serialize)] -pub struct Ai { +pub(crate) struct Ai { /// Whether or not the AI features are enabled. - pub enabled: Option<bool>, + pub(crate) enabled: Option<bool>, /// The address of the Atuin AI endpoint. Used for AI features like command generation. /// Only necessary for custom AI endpoints. - pub endpoint: Option<String>, + pub(crate) endpoint: Option<String>, /// The API token for the Atuin AI endpoint. Used for AI features like command generation. /// Only necessary for custom AI endpoints. - pub api_token: Option<String>, + pub(crate) api_token: Option<String>, /// Path to the AI sessions database. - pub db_path: String, + pub(crate) db_path: String, /// The maximum time in minutes that an AI session can be automatically resumed. - pub session_continue_minutes: i64, + pub(crate) session_continue_minutes: i64, /// Deprecated: use opening.send_cwd instead. Kept for backwards compatibility. #[serde(default)] - pub send_cwd: Option<bool>, + pub(crate) send_cwd: Option<bool>, /// Configuration for what context is sent in the opening AI request. #[serde(default)] - pub opening: AiOpening, + pub(crate) opening: AiOpening, /// Tool capability flags. #[serde(default)] - pub capabilities: AiCapabilities, + pub(crate) capabilities: AiCapabilities, } #[derive(Default, Clone, Debug, Deserialize, Serialize)] -pub struct AiCapabilities { +pub(crate) struct AiCapabilities { /// Whether the AI can request to search Atuin history. `None` = unset (defaults to enabled, and the ai will ask for permission). - pub enable_history_search: Option<bool>, + pub(crate) enable_history_search: Option<bool>, /// Whether the AI can request to view the stored output, if any, for Atuin history entries. `None` = unset (defaults to enabled, and the ai will ask for permission). - pub enable_history_output: Option<bool>, + pub(crate) enable_history_output: Option<bool>, /// Whether the AI can request to read and write files. `None` = unset (defaults to enabled, and the ai will ask for permission). - pub enable_file_tools: Option<bool>, + pub(crate) enable_file_tools: Option<bool>, /// Whether the AI can request to execute bash commands. `None` = unset (defaults to enabled, and the ai will ask for permission). - pub enable_command_execution: Option<bool>, + pub(crate) enable_command_execution: Option<bool>, } #[derive(Default, Clone, Debug, Deserialize, Serialize)] -pub struct AiOpening { +pub(crate) struct AiOpening { /// Whether or not to send the current working directory to the AI endpoint. - pub send_cwd: Option<bool>, + pub(crate) send_cwd: Option<bool>, /// Whether or not to send the last command as context in the opening AI request. - pub send_last_command: Option<bool>, + pub(crate) send_last_command: Option<bool>, } impl Default for Preview { @@ -730,72 +730,72 @@ impl Logs { /// Returns whether search logging is enabled. /// Uses search-specific setting if set, otherwise falls back to global. - pub fn search_enabled(&self) -> bool { + pub(crate) fn search_enabled(&self) -> bool { self.search.enabled.unwrap_or(self.enabled) } /// Returns whether daemon logging is enabled. /// Uses daemon-specific setting if set, otherwise falls back to global. - pub fn daemon_enabled(&self) -> bool { + pub(crate) fn daemon_enabled(&self) -> bool { self.daemon.enabled.unwrap_or(self.enabled) } /// Returns whether AI logging is enabled. /// Uses AI-specific setting if set, otherwise falls back to global. - pub fn ai_enabled(&self) -> bool { + pub(crate) fn ai_enabled(&self) -> bool { self.ai.enabled.unwrap_or(self.enabled) } /// Returns the log level for search logging. /// Uses search-specific setting if set, otherwise falls back to global. - pub fn search_level(&self) -> LogLevel { + pub(crate) fn search_level(&self) -> LogLevel { self.search.level.unwrap_or(self.level) } /// Returns the log level for daemon logging. /// Uses daemon-specific setting if set, otherwise falls back to global. - pub fn daemon_level(&self) -> LogLevel { + pub(crate) fn daemon_level(&self) -> LogLevel { self.daemon.level.unwrap_or(self.level) } /// Returns the log level for AI logging. /// Uses AI-specific setting if set, otherwise falls back to global. - pub fn ai_level(&self) -> LogLevel { + pub(crate) fn ai_level(&self) -> LogLevel { self.ai.level.unwrap_or(self.level) } /// Returns the retention days for search logging. /// Uses search-specific setting if set, otherwise falls back to global. - pub fn search_retention(&self) -> u64 { + pub(crate) fn search_retention(&self) -> u64 { self.search.retention.unwrap_or(self.retention) } /// Returns the retention days for daemon logging. /// Uses daemon-specific setting if set, otherwise falls back to global. - pub fn daemon_retention(&self) -> u64 { + pub(crate) fn daemon_retention(&self) -> u64 { self.daemon.retention.unwrap_or(self.retention) } /// Returns the retention days for AI logging. /// Uses AI-specific setting if set, otherwise falls back to global. - pub fn ai_retention(&self) -> u64 { + pub(crate) fn ai_retention(&self) -> u64 { self.ai.retention.unwrap_or(self.retention) } /// Returns the full path for the search log file. - pub fn search_path(&self) -> PathBuf { + pub(crate) fn search_path(&self) -> PathBuf { let path = PathBuf::from(&self.search.file); PathBuf::from(&self.dir).join(path) } /// Returns the full path for the daemon log file. - pub fn daemon_path(&self) -> PathBuf { + pub(crate) fn daemon_path(&self) -> PathBuf { let path = PathBuf::from(&self.daemon.file); PathBuf::from(&self.dir).join(path) } /// Returns the full path for the AI log file. - pub fn ai_path(&self) -> PathBuf { + pub(crate) fn ai_path(&self) -> PathBuf { let path = PathBuf::from(&self.ai.file); PathBuf::from(&self.dir).join(path) } @@ -832,7 +832,7 @@ impl Default for Tmux { // The preview height strategy also takes max_preview_height into account. #[derive(Clone, Debug, Deserialize, Copy, PartialEq, Eq, ValueEnum, Serialize)] -pub enum PreviewStrategy { +pub(crate) enum PreviewStrategy { // Preview height is calculated for the length of the selected command. #[serde(rename = "auto")] Auto, @@ -849,7 +849,7 @@ pub enum PreviewStrategy { /// Column types available for the interactive search UI. #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, Serialize)] #[serde(rename_all = "lowercase")] -pub enum UiColumnType { +pub(crate) enum UiColumnType { /// Command execution duration (e.g., "123ms") Duration, /// Relative time since execution (e.g., "59s ago") @@ -871,7 +871,7 @@ pub enum UiColumnType { impl UiColumnType { /// Returns the default width for this column type (in characters). /// The Command column returns 0 as it expands to fill remaining space. - pub fn default_width(&self) -> u16 { + pub(crate) fn default_width(&self) -> u16 { match self { UiColumnType::Duration => 5, // "814ms" UiColumnType::Time => 9, // "459ms ago" @@ -894,15 +894,15 @@ impl UiColumnType { /// A column configuration with type and optional custom width. /// Can be specified as just a string (uses default width) or as an object with type and width. #[derive(Clone, Debug, Serialize)] -pub struct UiColumn { - pub column_type: UiColumnType, - pub width: u16, +pub(crate) struct UiColumn { + pub(crate) column_type: UiColumnType, + pub(crate) width: u16, /// If true, this column expands to fill remaining space. Only one column should expand. - pub expand: bool, + pub(crate) expand: bool, } impl UiColumn { - pub fn new(column_type: UiColumnType) -> Self { + pub(crate) fn new(column_type: UiColumnType) -> Self { Self { width: column_type.default_width(), expand: column_type == UiColumnType::Command, @@ -910,7 +910,7 @@ impl UiColumn { } } - pub fn with_width(column_type: UiColumnType, width: u16) -> Self { + pub(crate) fn with_width(column_type: UiColumnType, width: u16) -> Self { Self { column_type, width, @@ -990,13 +990,13 @@ impl<'de> serde::Deserialize<'de> for UiColumn { /// UI-specific settings for the interactive search. #[derive(Clone, Debug, Deserialize, Serialize)] -pub struct Ui { +pub(crate) struct Ui { /// Columns to display in interactive search, from left to right. /// The indicator column (" > ") is always shown first implicitly. /// The "command" column should be last as it expands to fill remaining space. /// Can be simple strings or objects with type and width. #[serde(default = "Ui::default_columns")] - pub columns: Vec<UiColumn>, + pub(crate) columns: Vec<UiColumn>, } impl Ui { @@ -1010,7 +1010,7 @@ impl Ui { /// Validate the UI configuration. /// Returns an error if more than one column has expand = true. - pub fn validate(&self) -> Result<()> { + pub(crate) fn validate(&self) -> Result<()> { let expand_count = self.columns.iter().filter(|c| c.expand).count(); if expand_count > 1 { bail!( @@ -1031,103 +1031,103 @@ impl Default for Ui { } #[derive(Clone, Debug, Deserialize, Serialize)] -pub struct Settings { - pub data_dir: Option<String>, - pub dialect: Dialect, - pub timezone: Timezone, - pub style: Style, - pub auto_sync: bool, +pub(crate) struct Settings { + pub(crate) data_dir: Option<String>, + pub(crate) dialect: Dialect, + pub(crate) timezone: Timezone, + pub(crate) style: Style, + pub(crate) auto_sync: bool, /// The sync address for atuin. - pub sync_address: String, + pub(crate) sync_address: String, #[serde(default)] - pub sync_protocol: SyncProtocol, + pub(crate) sync_protocol: SyncProtocol, - pub sync_frequency: String, - pub db_path: String, - pub record_store_path: String, - pub key_path: String, - pub search_mode: SearchMode, - pub filter_mode: Option<FilterMode>, - pub filter_mode_shell_up_key_binding: Option<FilterMode>, - pub search_mode_shell_up_key_binding: Option<SearchMode>, - pub shell_up_key_binding: bool, - pub inline_height: u16, - pub inline_height_shell_up_key_binding: Option<u16>, - pub invert: bool, - pub show_preview: bool, - pub max_preview_height: u16, - pub show_help: bool, - pub show_tabs: bool, - pub show_numeric_shortcuts: bool, - pub auto_hide_height: u16, - pub exit_mode: ExitMode, - pub keymap_mode: KeymapMode, - pub keymap_mode_shell: KeymapMode, - pub keymap_cursor: HashMap<String, CursorStyle>, - pub word_jump_mode: WordJumpMode, - pub word_chars: String, - pub scroll_context_lines: usize, - pub history_format: String, - pub strip_trailing_whitespace: bool, - pub prefers_reduced_motion: bool, - pub store_failed: bool, - pub no_mouse: bool, + pub(crate) sync_frequency: String, + pub(crate) db_path: String, + pub(crate) record_store_path: String, + pub(crate) key_path: String, + pub(crate) search_mode: SearchMode, + pub(crate) filter_mode: Option<FilterMode>, + pub(crate) filter_mode_shell_up_key_binding: Option<FilterMode>, + pub(crate) search_mode_shell_up_key_binding: Option<SearchMode>, + pub(crate) shell_up_key_binding: bool, + pub(crate) inline_height: u16, + pub(crate) inline_height_shell_up_key_binding: Option<u16>, + pub(crate) invert: bool, + pub(crate) show_preview: bool, + pub(crate) max_preview_height: u16, + pub(crate) show_help: bool, + pub(crate) show_tabs: bool, + pub(crate) show_numeric_shortcuts: bool, + pub(crate) auto_hide_height: u16, + pub(crate) exit_mode: ExitMode, + pub(crate) keymap_mode: KeymapMode, + pub(crate) keymap_mode_shell: KeymapMode, + pub(crate) keymap_cursor: HashMap<String, CursorStyle>, + pub(crate) word_jump_mode: WordJumpMode, + pub(crate) word_chars: String, + pub(crate) scroll_context_lines: usize, + pub(crate) history_format: String, + pub(crate) strip_trailing_whitespace: bool, + pub(crate) prefers_reduced_motion: bool, + pub(crate) store_failed: bool, + pub(crate) no_mouse: bool, #[serde(with = "serde_regex", default = "RegexSet::empty", skip_serializing)] - pub history_filter: RegexSet, + pub(crate) history_filter: RegexSet, #[serde(with = "serde_regex", default = "RegexSet::empty", skip_serializing)] - pub cwd_filter: RegexSet, + pub(crate) cwd_filter: RegexSet, - pub secrets_filter: bool, - pub workspaces: bool, - pub ctrl_n_shortcuts: bool, + pub(crate) secrets_filter: bool, + pub(crate) workspaces: bool, + pub(crate) ctrl_n_shortcuts: bool, - pub network_connect_timeout: u64, - pub network_timeout: u64, - pub local_timeout: f64, - pub enter_accept: bool, - pub smart_sort: bool, - pub command_chaining: bool, + pub(crate) network_connect_timeout: u64, + pub(crate) network_timeout: u64, + pub(crate) local_timeout: f64, + pub(crate) enter_accept: bool, + pub(crate) smart_sort: bool, + pub(crate) command_chaining: bool, #[serde(default)] - pub stats: Stats, + pub(crate) stats: Stats, #[serde(default)] - pub keys: Keys, + pub(crate) keys: Keys, #[serde(default)] - pub keymap: KeymapConfig, + pub(crate) keymap: KeymapConfig, #[serde(default)] - pub preview: Preview, + pub(crate) preview: Preview, #[serde(default)] - pub daemon: Daemon, + pub(crate) daemon: Daemon, #[serde(default)] - pub search: Search, + pub(crate) search: Search, #[serde(default)] - pub theme: Theme, + pub(crate) theme: Theme, #[serde(default)] - pub ui: Ui, + pub(crate) ui: Ui, #[serde(default)] - pub tmux: Tmux, + pub(crate) tmux: Tmux, #[serde(default)] - pub logs: Logs, + pub(crate) logs: Logs, #[serde(default)] - pub meta: meta::Settings, + pub(crate) meta: meta::Settings, } impl Settings { - pub fn utc() -> Self { + pub(crate) fn utc() -> Self { Self::builder() .expect("Could not build default") .set_override("timezone", "0") @@ -1147,7 +1147,7 @@ impl Settings { // -- Meta store: lazily initialized on first access -- - pub async fn meta_store() -> Result<&'static crate::atuin_client::meta::MetaStore> { + pub(crate) async fn meta_store() -> Result<&'static crate::atuin_client::meta::MetaStore> { META_STORE .get_or_try_init(|| async { let (db_path, timeout) = META_CONFIG.get().ok_or_else(|| { @@ -1158,27 +1158,27 @@ impl Settings { .await } - pub async fn host_id() -> Result<HostId> { + pub(crate) async fn host_id() -> Result<HostId> { Self::meta_store().await?.host_id().await } - pub async fn last_sync() -> Result<OffsetDateTime> { + pub(crate) async fn last_sync() -> Result<OffsetDateTime> { Self::meta_store().await?.last_sync().await } - pub async fn save_sync_time() -> Result<()> { + pub(crate) async fn save_sync_time() -> Result<()> { Self::meta_store().await?.save_sync_time().await } - pub async fn last_version_check() -> Result<OffsetDateTime> { + pub(crate) async fn last_version_check() -> Result<OffsetDateTime> { Self::meta_store().await?.last_version_check().await } - pub async fn save_version_check_time() -> Result<()> { + pub(crate) async fn save_version_check_time() -> Result<()> { Self::meta_store().await?.save_version_check_time().await } - pub async fn should_sync(&self) -> Result<bool> { + pub(crate) async fn should_sync(&self) -> Result<bool> { if !self.auto_sync || !Self::meta_store().await?.logged_in().await? { return Ok(false); } @@ -1196,11 +1196,11 @@ impl Settings { } } - pub async fn logged_in(&self) -> Result<bool> { + pub(crate) async fn logged_in(&self) -> Result<bool> { Self::meta_store().await?.logged_in().await } - pub async fn session_token(&self) -> Result<String> { + pub(crate) async fn session_token(&self) -> Result<String> { match Self::meta_store().await?.session_token().await? { Some(token) => Ok(token), None => Err(eyre!("Tried to load session; not logged in")), @@ -1211,7 +1211,7 @@ impl Settings { /// the correct auth strategy. Also performs cleanup of mis-stored tokens /// (e.g. a CLI token incorrectly saved in the Hub session slot). #[cfg(feature = "sync")] - pub async fn resolve_sync_auth(&self) -> SyncAuth { + pub(crate) async fn resolve_sync_auth(&self) -> SyncAuth { let meta = match Self::meta_store().await { Ok(m) => m, Err(e) => { @@ -1238,11 +1238,11 @@ impl Settings { /// `AuthToken`. Callers that need to distinguish between auth states /// (e.g. to show different UI) should call `resolve_sync_auth` directly. #[cfg(feature = "sync")] - pub async fn sync_auth_token(&self) -> Result<crate::atuin_client::api_client::AuthToken> { + pub(crate) async fn sync_auth_token(&self) -> Result<crate::atuin_client::api_client::AuthToken> { self.resolve_sync_auth().await.into_auth_token() } - pub fn default_filter_mode(&self, git_root: bool) -> FilterMode { + pub(crate) fn default_filter_mode(&self, git_root: bool) -> FilterMode { self.filter_mode .filter(|x| self.search.filters.contains(x)) .or_else(|| { @@ -1259,7 +1259,7 @@ impl Settings { .unwrap_or(FilterMode::Global) } - pub fn builder() -> Result<ConfigBuilder<DefaultState>> { + pub(crate) fn builder() -> Result<ConfigBuilder<DefaultState>> { Self::builder_with_data_dir(&crate::atuin_common::utils::data_dir()) } @@ -1386,7 +1386,7 @@ impl Settings { )) } - pub fn get_config_path() -> Result<PathBuf> { + pub(crate) fn get_config_path() -> Result<PathBuf> { let config_dir = crate::atuin_common::utils::config_dir(); create_dir_all(&config_dir) @@ -1508,7 +1508,7 @@ impl Settings { /// Returns the effective value after merging defaults, config file, and /// environment — without the side-effects of full `Settings` construction /// (meta store init, path expansion, etc.). - pub fn get_config_value(key: &str) -> Result<String> { + pub(crate) fn get_config_value(key: &str) -> Result<String> { let config = Self::build_config()?; let value: config::Value = config .get(key) @@ -1567,7 +1567,7 @@ impl Settings { } } - pub fn new() -> Result<Self> { + pub(crate) fn new() -> Result<Self> { let config = Self::build_config()?; let settings: Settings = config .try_deserialize() @@ -1590,7 +1590,7 @@ impl Settings { .map_err(|e| eyre!("failed to expand path: {}", e)) } - pub fn paths_ok(&self) -> bool { + pub(crate) fn paths_ok(&self) -> bool { let paths = [ &self.db_path, &self.record_store_path, @@ -1624,7 +1624,7 @@ impl Default for Settings { /// This function is not thread-safe with concurrent calls to Settings::new() /// or other meta store initialization. Only call from tests. #[doc(hidden)] -pub fn init_meta_config_for_testing(meta_db_path: impl Into<String>, local_timeout: f64) { +pub(crate) fn init_meta_config_for_testing(meta_db_path: impl Into<String>, local_timeout: f64) { META_CONFIG.set((meta_db_path.into(), local_timeout)).ok(); } diff --git a/crates/turtle/src/atuin_client/settings/meta.rs b/crates/turtle/src/atuin_client/settings/meta.rs index 450d0432..cc5afcf7 100644 --- a/crates/turtle/src/atuin_client/settings/meta.rs +++ b/crates/turtle/src/atuin_client/settings/meta.rs @@ -1,8 +1,8 @@ use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize, Clone)] -pub struct Settings { - pub db_path: String, +pub(crate) struct Settings { + pub(crate) db_path: String, } impl Default for Settings { diff --git a/crates/turtle/src/atuin_client/settings/watcher.rs b/crates/turtle/src/atuin_client/settings/watcher.rs index 7548573e..20082639 100644 --- a/crates/turtle/src/atuin_client/settings/watcher.rs +++ b/crates/turtle/src/atuin_client/settings/watcher.rs @@ -44,7 +44,7 @@ static SETTINGS_WATCHER: OnceLock<Result<SettingsWatcher, String>> = OnceLock::n /// /// Initializes the watcher on first call. Subsequent calls return the same instance. /// The watcher monitors the config file for changes and broadcasts updates. -pub fn global_settings_watcher() -> Result<&'static SettingsWatcher> { +pub(crate) fn global_settings_watcher() -> Result<&'static SettingsWatcher> { let result = SETTINGS_WATCHER.get_or_init(|| SettingsWatcher::new().map_err(|e| e.to_string())); match result { @@ -57,7 +57,7 @@ pub fn global_settings_watcher() -> Result<&'static SettingsWatcher> { /// /// Uses `notify` for cross-platform file watching and `tokio::sync::watch` /// for efficient broadcast to multiple subscribers. -pub struct SettingsWatcher { +pub(crate) struct SettingsWatcher { /// Receiver for settings updates. Clone this to subscribe. rx: watch::Receiver<Arc<Settings>>, /// Keeps the file watcher alive for the lifetime of this struct. @@ -69,7 +69,7 @@ impl SettingsWatcher { /// /// Loads initial settings and starts watching the config file for changes. /// Changes are debounced (500ms) to avoid multiple reloads during saves. - pub fn new() -> Result<Self> { + pub(crate) fn new() -> Result<Self> { let initial_settings = Arc::new(Settings::new()?); let (tx, rx) = watch::channel(initial_settings); @@ -89,12 +89,12 @@ impl SettingsWatcher { /// Returns a receiver that will be notified when settings change. /// Use `changed().await` to wait for the next update, then `borrow()` /// to access the current settings. - pub fn subscribe(&self) -> watch::Receiver<Arc<Settings>> { + pub(crate) fn subscribe(&self) -> watch::Receiver<Arc<Settings>> { self.rx.clone() } /// Get the current settings without subscribing to updates. - pub fn current(&self) -> Arc<Settings> { + pub(crate) fn current(&self) -> Arc<Settings> { self.rx.borrow().clone() } diff --git a/crates/turtle/src/atuin_client/sync.rs b/crates/turtle/src/atuin_client/sync.rs index 361b6636..46efdab9 100644 --- a/crates/turtle/src/atuin_client/sync.rs +++ b/crates/turtle/src/atuin_client/sync.rs @@ -15,7 +15,7 @@ use crate::atuin_client::{ settings::Settings, }; -pub fn hash_str(string: &str) -> String { +pub(crate) fn hash_str(string: &str) -> String { use sha2::{Digest, Sha256}; let mut hasher = Sha256::new(); hasher.update(string.as_bytes()); @@ -192,7 +192,7 @@ async fn sync_upload( Ok(()) } -pub async fn sync(settings: &Settings, force: bool, db: &impl Database) -> Result<()> { +pub(crate) async fn sync(settings: &Settings, force: bool, db: &impl Database) -> Result<()> { let client = api_client::Client::new( &settings.sync_address, settings.sync_auth_token().await?, diff --git a/crates/turtle/src/atuin_client/theme.rs b/crates/turtle/src/atuin_client/theme.rs index 1d9c0b9e..21bbe07c 100644 --- a/crates/turtle/src/atuin_client/theme.rs +++ b/crates/turtle/src/atuin_client/theme.rs @@ -21,7 +21,7 @@ static DEFAULT_MAX_DEPTH: u8 = 10; Serialize, Deserialize, Copy, Clone, Hash, Debug, Eq, PartialEq, strum_macros::Display, )] #[strum(serialize_all = "camel_case")] -pub enum Meaning { +pub(crate) enum Meaning { AlertInfo, AlertWarn, AlertError, @@ -34,31 +34,31 @@ pub enum Meaning { } #[derive(Clone, Debug, Deserialize, Serialize)] -pub struct ThemeConfig { +pub(crate) struct ThemeConfig { // Definition of the theme - pub theme: ThemeDefinitionConfigBlock, + pub(crate) theme: ThemeDefinitionConfigBlock, // Colors - pub colors: HashMap<Meaning, String>, + pub(crate) colors: HashMap<Meaning, String>, } #[derive(Clone, Debug, Deserialize, Serialize)] -pub struct ThemeDefinitionConfigBlock { +pub(crate) struct ThemeDefinitionConfigBlock { /// Name of theme ("default" for base) - pub name: String, + pub(crate) name: String, /// Whether any theme should be treated as a parent _if available_ - pub parent: Option<String>, + pub(crate) parent: Option<String>, } use crossterm::style::{Attribute, Attributes, Color, ContentStyle}; // For now, a theme is loaded as a mapping of meanings to colors, but it may be desirable to // expand that in the future to general styles, so we populate a Meaning->ContentStyle hashmap. -pub struct Theme { - pub name: String, - pub parent: Option<String>, - pub styles: HashMap<Meaning, ContentStyle>, +pub(crate) struct Theme { + pub(crate) name: String, + pub(crate) parent: Option<String>, + pub(crate) styles: HashMap<Meaning, ContentStyle>, } // Themes have a number of convenience functions for the most commonly used meanings. @@ -66,29 +66,29 @@ pub struct Theme { // theme-related boilerplate minimal, the convenience functions give a color. impl Theme { // This is the base "default" color, for general text - pub fn get_base(&self) -> ContentStyle { + pub(crate) fn get_base(&self) -> ContentStyle { self.styles[&Meaning::Base] } - pub fn get_info(&self) -> ContentStyle { + pub(crate) fn get_info(&self) -> ContentStyle { self.get_alert(log::Level::Info) } - pub fn get_warning(&self) -> ContentStyle { + pub(crate) fn get_warning(&self) -> ContentStyle { self.get_alert(log::Level::Warn) } - pub fn get_error(&self) -> ContentStyle { + pub(crate) fn get_error(&self) -> ContentStyle { self.get_alert(log::Level::Error) } // The alert meanings may be chosen by the Level enum, rather than the methods above // or the full Meaning enum, to simplify programmatic selection of a log-level. - pub fn get_alert(&self, severity: log::Level) -> ContentStyle { + pub(crate) fn get_alert(&self, severity: log::Level) -> ContentStyle { self.styles[ALERT_TYPES.get(&severity).unwrap()] } - pub fn new( + pub(crate) fn new( name: String, parent: Option<String>, styles: HashMap<Meaning, ContentStyle>, @@ -100,7 +100,7 @@ impl Theme { } } - pub fn closest_meaning<'a>(&self, meaning: &'a Meaning) -> &'a Meaning { + pub(crate) fn closest_meaning<'a>(&self, meaning: &'a Meaning) -> &'a Meaning { if self.styles.contains_key(meaning) { meaning } else if MEANING_FALLBACKS.contains_key(meaning) { @@ -111,7 +111,7 @@ impl Theme { } // General access - if you have a meaning, this will give you a (crossterm) style - pub fn as_style(&self, meaning: Meaning) -> ContentStyle { + pub(crate) fn as_style(&self, meaning: Meaning) -> ContentStyle { self.styles[self.closest_meaning(&meaning)] } @@ -120,7 +120,7 @@ impl Theme { // but we do not have this on in general, as it could print unfiltered text to the terminal // from a theme TOML file. However, it will always return a theme, falling back to // defaults on error, so that a TOML file does not break loading - pub fn from_foreground_colors( + pub(crate) fn from_foreground_colors( name: String, parent: Option<&Theme>, foreground_colors: HashMap<Meaning, String>, @@ -206,7 +206,7 @@ fn from_string(name: &str) -> Result<Color, String> { } } -pub struct StyleFactory {} +pub(crate) struct StyleFactory {} impl StyleFactory { fn from_fg_string(name: &str) -> Result<ContentStyle, String> { @@ -360,7 +360,7 @@ static BUILTIN_THEMES: LazyLock<HashMap<&'static str, Theme>> = LazyLock::new(|| }); // To avoid themes being repeatedly loaded, we store them in a theme manager -pub struct ThemeManager { +pub(crate) struct ThemeManager { loaded_themes: HashMap<String, Theme>, debug: bool, override_theme_dir: Option<String>, @@ -368,7 +368,7 @@ pub struct ThemeManager { // Theme-loading logic impl ThemeManager { - pub fn new(debug: Option<bool>, theme_dir: Option<String>) -> Self { + pub(crate) fn new(debug: Option<bool>, theme_dir: Option<String>) -> Self { Self { loaded_themes: HashMap::new(), debug: debug.unwrap_or(false), @@ -381,7 +381,7 @@ impl ThemeManager { // Try to load a theme from a `{name}.toml` file in the theme directory. If an override is set // for the theme dir (via ATUIN_THEME_DIR env) we should load the theme from there - pub fn load_theme_from_file( + pub(crate) fn load_theme_from_file( &mut self, name: &str, max_depth: u8, @@ -421,7 +421,7 @@ impl ThemeManager { self.load_theme_from_config(name, config, max_depth) } - pub fn load_theme_from_config( + pub(crate) fn load_theme_from_config( &mut self, name: &str, config: Config, @@ -475,7 +475,7 @@ impl ThemeManager { // Check if the requested theme is loaded and, if not, then attempt to get it // from the builtins or, if not there, from file - pub fn load_theme(&mut self, name: &str, max_depth: Option<u8>) -> &Theme { + pub(crate) fn load_theme(&mut self, name: &str, max_depth: Option<u8>) -> &Theme { if self.loaded_themes.contains_key(name) { return self.loaded_themes.get(name).unwrap(); } |
