diff options
| author | Benedikt Peetz <benedikt.peetz@b-peetz.de> | 2026-06-11 14:20:49 +0200 |
|---|---|---|
| committer | Benedikt Peetz <benedikt.peetz@b-peetz.de> | 2026-06-11 14:20:49 +0200 |
| commit | 199563550dd41c3dfb703bd3747604a8a03cdbc5 (patch) | |
| tree | 30cfa3e5539f782b7571091c742ee1c219e138fb | |
| parent | chore: Restore db migrations (diff) | |
| download | atuin-199563550dd41c3dfb703bd3747604a8a03cdbc5.zip | |
chore: Remove all `pub`s
They will not be marked by rustc/cargo as unused, and as atuin doesn't
expose an API all of them _should_ be `pub(crate)`
142 files changed, 1259 insertions, 1259 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(); } diff --git a/crates/turtle/src/atuin_common/api.rs b/crates/turtle/src/atuin_common/api.rs index 1a9f348c..2f909676 100644 --- a/crates/turtle/src/atuin_common/api.rs +++ b/crates/turtle/src/atuin_common/api.rs @@ -5,140 +5,140 @@ use std::sync::LazyLock; use time::OffsetDateTime; // the usage of X- has been deprecated for quite along time, it turns out -pub static ATUIN_HEADER_VERSION: &str = "Atuin-Version"; -pub static ATUIN_CARGO_VERSION: &str = env!("CARGO_PKG_VERSION"); +pub(crate) static ATUIN_HEADER_VERSION: &str = "Atuin-Version"; +pub(crate) static ATUIN_CARGO_VERSION: &str = env!("CARGO_PKG_VERSION"); -pub static ATUIN_VERSION: LazyLock<Version> = +pub(crate) static ATUIN_VERSION: LazyLock<Version> = LazyLock::new(|| Version::parse(ATUIN_CARGO_VERSION).expect("failed to parse self semver")); #[derive(Debug, Serialize, Deserialize)] -pub struct UserResponse { - pub username: String, +pub(crate) struct UserResponse { + pub(crate) username: String, } #[derive(Debug, Serialize, Deserialize)] -pub struct RegisterRequest { - pub email: String, - pub username: String, - pub password: String, +pub(crate) struct RegisterRequest { + pub(crate) email: String, + pub(crate) username: String, + pub(crate) password: String, } #[derive(Debug, Serialize, Deserialize)] -pub struct RegisterResponse { - pub session: String, +pub(crate) struct RegisterResponse { + pub(crate) session: String, /// Auth type: "hub" for Hub API tokens, "cli" for legacy CLI session tokens. /// Old servers that don't return this field will deserialize as None. #[serde(default)] - pub auth: Option<String>, + pub(crate) auth: Option<String>, } #[derive(Debug, Serialize, Deserialize)] -pub struct DeleteUserResponse {} +pub(crate) struct DeleteUserResponse {} #[derive(Debug, Serialize, Deserialize)] -pub struct ChangePasswordRequest { - pub current_password: String, - pub new_password: String, +pub(crate) struct ChangePasswordRequest { + pub(crate) current_password: String, + pub(crate) new_password: String, } #[derive(Debug, Serialize, Deserialize)] -pub struct ChangePasswordResponse {} +pub(crate) struct ChangePasswordResponse {} #[derive(Debug, Serialize, Deserialize)] -pub struct LoginRequest { - pub username: String, - pub password: String, +pub(crate) struct LoginRequest { + pub(crate) username: String, + pub(crate) password: String, } #[derive(Debug, Serialize, Deserialize)] -pub struct LoginResponse { - pub session: String, +pub(crate) struct LoginResponse { + pub(crate) session: String, /// Auth type: "hub" for Hub API tokens, "cli" for legacy CLI session tokens. /// Old servers that don't return this field will deserialize as None. #[serde(default)] - pub auth: Option<String>, + pub(crate) auth: Option<String>, } #[derive(Debug, Serialize, Deserialize)] -pub struct AddHistoryRequest { - pub id: String, +pub(crate) struct AddHistoryRequest { + pub(crate) id: String, #[serde(with = "time::serde::rfc3339")] - pub timestamp: OffsetDateTime, - pub data: String, - pub hostname: String, + pub(crate) timestamp: OffsetDateTime, + pub(crate) data: String, + pub(crate) hostname: String, } #[derive(Debug, Serialize, Deserialize)] -pub struct CountResponse { - pub count: i64, +pub(crate) struct CountResponse { + pub(crate) count: i64, } #[derive(Debug, Serialize, Deserialize)] -pub struct SyncHistoryRequest { +pub(crate) struct SyncHistoryRequest { #[serde(with = "time::serde::rfc3339")] - pub sync_ts: OffsetDateTime, + pub(crate) sync_ts: OffsetDateTime, #[serde(with = "time::serde::rfc3339")] - pub history_ts: OffsetDateTime, - pub host: String, + pub(crate) history_ts: OffsetDateTime, + pub(crate) host: String, } #[derive(Debug, Serialize, Deserialize)] -pub struct SyncHistoryResponse { - pub history: Vec<String>, +pub(crate) struct SyncHistoryResponse { + pub(crate) history: Vec<String>, } #[derive(Debug, Serialize, Deserialize)] -pub struct ErrorResponse<'a> { - pub reason: Cow<'a, str>, +pub(crate) struct ErrorResponse<'a> { + pub(crate) reason: Cow<'a, str>, } #[derive(Debug, Serialize, Deserialize)] -pub struct IndexResponse { - pub homage: String, - pub version: String, +pub(crate) struct IndexResponse { + pub(crate) homage: String, + pub(crate) version: String, } #[derive(Debug, Serialize, Deserialize)] -pub struct StatusResponse { - pub count: i64, - pub username: String, - pub deleted: Vec<String>, +pub(crate) struct StatusResponse { + pub(crate) count: i64, + pub(crate) username: String, + pub(crate) deleted: Vec<String>, // These could/should also go on the index of the server // However, we do not request the server index as a part of normal sync // I'd rather slightly increase the size of this response, than add an extra HTTP request - pub page_size: i64, // max page size supported by the server - pub version: String, + pub(crate) page_size: i64, // max page size supported by the server + pub(crate) version: String, } #[derive(Debug, Serialize, Deserialize)] -pub struct DeleteHistoryRequest { - pub client_id: String, +pub(crate) struct DeleteHistoryRequest { + pub(crate) client_id: String, } #[derive(Debug, Serialize, Deserialize)] -pub struct MessageResponse { - pub message: String, +pub(crate) struct MessageResponse { + pub(crate) message: String, } #[derive(Debug, Serialize, Deserialize)] -pub struct MeResponse { - pub username: String, +pub(crate) struct MeResponse { + pub(crate) username: String, } // Hub CLI authentication types /// Response from POST /auth/cli/code - generates a code for CLI auth #[derive(Debug, Serialize, Deserialize)] -pub struct CliCodeResponse { - pub code: String, +pub(crate) struct CliCodeResponse { + pub(crate) code: String, } /// Response from GET /auth/cli/verify?code=<code> - polls for authorization #[derive(Debug, Serialize, Deserialize)] -pub struct CliVerifyResponse { +pub(crate) struct CliVerifyResponse { /// Session token, present only when authorization is complete - pub token: Option<String>, - pub success: Option<bool>, - pub error: Option<String>, + pub(crate) token: Option<String>, + pub(crate) success: Option<bool>, + pub(crate) error: Option<String>, } diff --git a/crates/turtle/src/atuin_common/calendar.rs b/crates/turtle/src/atuin_common/calendar.rs index d3b1d921..befe8c2e 100644 --- a/crates/turtle/src/atuin_common/calendar.rs +++ b/crates/turtle/src/atuin_common/calendar.rs @@ -1,16 +1,16 @@ // Calendar data use serde::{Serialize, Deserialize}; -pub enum TimePeriod { +pub(crate) enum TimePeriod { YEAR, MONTH, DAY, } #[derive(Debug, Serialize, Deserialize)] -pub struct TimePeriodInfo { - pub count: u64, +pub(crate) struct TimePeriodInfo { + pub(crate) count: u64, // TODO: Use this for merkle tree magic - pub hash: String, + pub(crate) hash: String, } diff --git a/crates/turtle/src/atuin_common/mod.rs b/crates/turtle/src/atuin_common/mod.rs index d886520d..635c9fc3 100644 --- a/crates/turtle/src/atuin_common/mod.rs +++ b/crates/turtle/src/atuin_common/mod.rs @@ -14,7 +14,7 @@ macro_rules! new_uuid { serde::Deserialize, )] #[serde(transparent)] - pub struct $name(pub Uuid); + pub(crate) struct $name(pub(crate) Uuid); impl<DB: sqlx::Database> sqlx::Type<DB> for $name where @@ -51,8 +51,8 @@ macro_rules! new_uuid { }; } -pub mod api; -pub mod record; -pub mod shell; -pub mod tls; -pub mod utils; +pub(crate) mod api; +pub(crate) mod record; +pub(crate) mod shell; +pub(crate) mod tls; +pub(crate) mod utils; diff --git a/crates/turtle/src/atuin_common/record.rs b/crates/turtle/src/atuin_common/record.rs index 05c29338..9db9cf98 100644 --- a/crates/turtle/src/atuin_common/record.rs +++ b/crates/turtle/src/atuin_common/record.rs @@ -6,30 +6,30 @@ use typed_builder::TypedBuilder; use uuid::Uuid; #[derive(Clone, Debug, PartialEq)] -pub struct DecryptedData(pub Vec<u8>); +pub(crate) struct DecryptedData(pub(crate) Vec<u8>); #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub struct EncryptedData { - pub data: String, - pub content_encryption_key: String, +pub(crate) struct EncryptedData { + pub(crate) data: String, + pub(crate) content_encryption_key: String, } #[derive(Debug, PartialEq, PartialOrd, Ord, Eq)] -pub struct Diff { - pub host: HostId, - pub tag: String, - pub local: Option<RecordIdx>, - pub remote: Option<RecordIdx>, +pub(crate) struct Diff { + pub(crate) host: HostId, + pub(crate) tag: String, + pub(crate) local: Option<RecordIdx>, + pub(crate) remote: Option<RecordIdx>, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] -pub struct Host { - pub id: HostId, - pub name: String, +pub(crate) struct Host { + pub(crate) id: HostId, + pub(crate) name: String, } impl Host { - pub fn new(id: HostId) -> Self { + pub(crate) fn new(id: HostId) -> Self { Host { id, name: String::new(), @@ -40,51 +40,51 @@ impl Host { new_uuid!(RecordId); new_uuid!(HostId); -pub type RecordIdx = u64; +pub(crate) type RecordIdx = u64; /// A single record stored inside of our local database #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, TypedBuilder)] -pub struct Record<Data> { +pub(crate) struct Record<Data> { /// a unique ID #[builder(default = RecordId(crate::atuin_common::utils::uuid_v7()))] - pub id: RecordId, + pub(crate) id: RecordId, /// The integer record ID. This is only unique per (host, tag). - pub idx: RecordIdx, + pub(crate) idx: RecordIdx, /// The unique ID of the host. // TODO(ellie): Optimize the storage here. We use a bunch of IDs, and currently store // as strings. I would rather avoid normalization, so store as UUID binary instead of // encoding to a string and wasting much more storage. - pub host: Host, + pub(crate) host: Host, /// The creation time in nanoseconds since unix epoch #[builder(default = time::OffsetDateTime::now_utc().unix_timestamp_nanos() as u64)] - pub timestamp: u64, + pub(crate) timestamp: u64, /// The version the data in the entry conforms to // However we want to track versions for this tag, eg v2 - pub version: String, + pub(crate) version: String, /// The type of data we are storing here. Eg, "history" - pub tag: String, + pub(crate) tag: String, /// Some data. This can be anything you wish to store. Use the tag field to know how to handle it. - pub data: Data, + pub(crate) data: Data, } /// Extra data from the record that should be encoded in the data #[derive(Debug, Copy, Clone)] -pub struct AdditionalData<'a> { - pub id: &'a RecordId, - pub idx: &'a u64, - pub version: &'a str, - pub tag: &'a str, - pub host: &'a HostId, +pub(crate) struct AdditionalData<'a> { + pub(crate) id: &'a RecordId, + pub(crate) idx: &'a u64, + pub(crate) version: &'a str, + pub(crate) tag: &'a str, + pub(crate) host: &'a HostId, } impl<Data> Record<Data> { - pub fn append(&self, data: Vec<u8>) -> Record<DecryptedData> { + pub(crate) fn append(&self, data: Vec<u8>) -> Record<DecryptedData> { Record::builder() .host(self.host.clone()) .version(self.version.clone()) @@ -98,9 +98,9 @@ impl<Data> Record<Data> { /// An index representing the current state of the record stores /// This can be both remote, or local, and compared in either direction #[derive(Debug, Serialize, Deserialize)] -pub struct RecordStatus { +pub(crate) struct RecordStatus { // A map of host -> tag -> max(idx) - pub hosts: HashMap<HostId, HashMap<String, RecordIdx>>, + pub(crate) hosts: HashMap<HostId, HashMap<String, RecordIdx>>, } impl Default for RecordStatus { @@ -118,22 +118,22 @@ impl Extend<(HostId, String, RecordIdx)> for RecordStatus { } impl RecordStatus { - pub fn new() -> RecordStatus { + pub(crate) fn new() -> RecordStatus { RecordStatus { hosts: HashMap::new(), } } /// Insert a new tail record into the store - pub fn set(&mut self, tail: Record<DecryptedData>) { + pub(crate) fn set(&mut self, tail: Record<DecryptedData>) { self.set_raw(tail.host.id, tail.tag, tail.idx) } - pub fn set_raw(&mut self, host: HostId, tag: String, tail_id: RecordIdx) { + pub(crate) fn set_raw(&mut self, host: HostId, tag: String, tail_id: RecordIdx) { self.hosts.entry(host).or_default().insert(tag, tail_id); } - pub fn get(&self, host: HostId, tag: String) -> Option<RecordIdx> { + pub(crate) fn get(&self, host: HostId, tag: String) -> Option<RecordIdx> { self.hosts.get(&host).and_then(|v| v.get(&tag)).cloned() } @@ -144,7 +144,7 @@ impl RecordStatus { /// then we need to do some downloading. If it is smaller, then we need to do some uploading /// Note that we cannot upload if we are not the owner of the record store - hosts can only /// write to their own store. - pub fn diff(&self, other: &Self) -> Vec<Diff> { + pub(crate) fn diff(&self, other: &Self) -> Vec<Diff> { let mut ret = Vec::new(); // First, we check if other has everything that self has @@ -199,7 +199,7 @@ impl RecordStatus { } } -pub trait Encryption { +pub(crate) trait Encryption { fn re_encrypt( data: EncryptedData, ad: AdditionalData, @@ -214,7 +214,7 @@ pub trait Encryption { } impl Record<DecryptedData> { - pub fn encrypt<E: Encryption>(self, key: &[u8; 32]) -> Record<EncryptedData> { + pub(crate) fn encrypt<E: Encryption>(self, key: &[u8; 32]) -> Record<EncryptedData> { let ad = AdditionalData { id: &self.id, version: &self.version, @@ -235,7 +235,7 @@ impl Record<DecryptedData> { } impl Record<EncryptedData> { - pub fn decrypt<E: Encryption>(self, key: &[u8; 32]) -> Result<Record<DecryptedData>> { + pub(crate) fn decrypt<E: Encryption>(self, key: &[u8; 32]) -> Result<Record<DecryptedData>> { let ad = AdditionalData { id: &self.id, version: &self.version, @@ -254,7 +254,7 @@ impl Record<EncryptedData> { }) } - pub fn re_encrypt<E: Encryption>( + pub(crate) fn re_encrypt<E: Encryption>( self, old_key: &[u8; 32], new_key: &[u8; 32], diff --git a/crates/turtle/src/atuin_common/shell.rs b/crates/turtle/src/atuin_common/shell.rs index 7f9a7b8f..dbd9b982 100644 --- a/crates/turtle/src/atuin_common/shell.rs +++ b/crates/turtle/src/atuin_common/shell.rs @@ -5,7 +5,7 @@ use sysinfo::{Process, System, get_current_pid}; use thiserror::Error; #[derive(PartialEq)] -pub enum Shell { +pub(crate) enum Shell { Sh, Bash, Fish, @@ -36,7 +36,7 @@ impl std::fmt::Display for Shell { } #[derive(Debug, Error, Serialize)] -pub enum ShellError { +pub(crate) enum ShellError { #[error("shell not supported")] NotSupported, @@ -45,7 +45,7 @@ pub enum ShellError { } impl Shell { - pub fn current() -> Shell { + pub(crate) fn current() -> Shell { let sys = System::new_all(); let process = sys @@ -62,13 +62,13 @@ impl Shell { Shell::from_string(shell.to_string()) } - pub fn from_env() -> Shell { + pub(crate) fn from_env() -> Shell { std::env::var("ATUIN_SHELL").map_or(Shell::Unknown, |shell| { Shell::from_string(shell.trim().to_lowercase()) }) } - pub fn config_file(&self) -> Option<std::path::PathBuf> { + pub(crate) fn config_file(&self) -> Option<std::path::PathBuf> { let mut path = if let Some(base) = directories::BaseDirs::new() { base.home_dir().to_owned() } else { @@ -90,7 +90,7 @@ impl Shell { /// Best-effort attempt to determine the default shell /// This implementation will be different across different platforms /// Caller should ensure to handle Shell::Unknown correctly - pub fn default_shell() -> Result<Shell, ShellError> { + pub(crate) fn default_shell() -> Result<Shell, ShellError> { let sys = System::name().unwrap_or("".to_string()).to_lowercase(); // TODO: Support Linux @@ -118,7 +118,7 @@ impl Shell { )) } - pub fn from_string(name: String) -> Shell { + pub(crate) fn from_string(name: String) -> Shell { match name.as_str() { "bash" => Shell::Bash, "fish" => Shell::Fish, @@ -135,11 +135,11 @@ impl Shell { /// Returns true if the shell is posix-like /// Note that while fish is not posix compliant, it behaves well enough for our current /// featureset that this does not matter. - pub fn is_posixish(&self) -> bool { + pub(crate) fn is_posixish(&self) -> bool { matches!(self, Shell::Bash | Shell::Fish | Shell::Zsh) } - pub fn run_interactive<I, S>(&self, args: I) -> Result<String, ShellError> + pub(crate) fn run_interactive<I, S>(&self, args: I) -> Result<String, ShellError> where I: IntoIterator<Item = S>, S: AsRef<OsStr>, @@ -162,7 +162,7 @@ impl Shell { } } -pub fn shell_name(parent: Option<&Process>) -> String { +pub(crate) fn shell_name(parent: Option<&Process>) -> String { let sys = System::new_all(); let parent = if let Some(parent) = parent { diff --git a/crates/turtle/src/atuin_common/tls.rs b/crates/turtle/src/atuin_common/tls.rs index e8c840e0..3736f878 100644 --- a/crates/turtle/src/atuin_common/tls.rs +++ b/crates/turtle/src/atuin_common/tls.rs @@ -6,7 +6,7 @@ static INIT: Once = Once::new(); /// /// Must be called before creating any reqwest clients. Safe to call /// multiple times — only the first call installs the provider. -pub fn ensure_crypto_provider() { +pub(crate) fn ensure_crypto_provider() { INIT.call_once(|| { rustls::crypto::ring::default_provider() .install_default() diff --git a/crates/turtle/src/atuin_common/utils.rs b/crates/turtle/src/atuin_common/utils.rs index d7382fb2..81eb1178 100644 --- a/crates/turtle/src/atuin_common/utils.rs +++ b/crates/turtle/src/atuin_common/utils.rs @@ -9,7 +9,7 @@ use getrandom::getrandom; use uuid::Uuid; /// Generate N random bytes, using a cryptographically secure source -pub fn crypto_random_bytes<const N: usize>() -> [u8; N] { +pub(crate) fn crypto_random_bytes<const N: usize>() -> [u8; N] { // rand say they are in principle safe for crypto purposes, but that it is perhaps a better // idea to use getrandom for things such as passwords. let mut ret = [0u8; N]; @@ -20,7 +20,7 @@ pub fn crypto_random_bytes<const N: usize>() -> [u8; N] { } /// Generate N random bytes using a cryptographically secure source, return encoded as a string -pub fn crypto_random_string<const N: usize>() -> String { +pub(crate) fn crypto_random_string<const N: usize>() -> String { let bytes = crypto_random_bytes::<N>(); // We only use this to create a random string, and won't be reversing it to find the original @@ -28,15 +28,15 @@ pub fn crypto_random_string<const N: usize>() -> String { BASE64_URL_SAFE_NO_PAD.encode(bytes) } -pub fn uuid_v7() -> Uuid { +pub(crate) fn uuid_v7() -> Uuid { Uuid::now_v7() } -pub fn uuid_v4() -> String { +pub(crate) fn uuid_v4() -> String { Uuid::new_v4().as_simple().to_string() } -pub fn has_git_dir(path: &str) -> bool { +pub(crate) fn has_git_dir(path: &str) -> bool { let mut gitdir = PathBuf::from(path); gitdir.push(".git"); @@ -78,7 +78,7 @@ fn resolve_git_worktree(path: &Path) -> Option<PathBuf> { // detect if any parent dir has a git repo in it // I really don't want to bring in libgit for something simple like this // If we start to do anything more advanced, then perhaps -pub fn in_git_repo(path: &str) -> Option<PathBuf> { +pub(crate) fn in_git_repo(path: &str) -> Option<PathBuf> { let mut gitdir = PathBuf::from(path); while gitdir.parent().is_some() && !has_git_dir(gitdir.to_str().unwrap()) { @@ -101,34 +101,34 @@ pub fn in_git_repo(path: &str) -> Option<PathBuf> { // I don't want to use ProjectDirs, it puts config in awkward places on // mac. Data too. Seems to be more intended for GUI apps. -pub fn home_dir() -> PathBuf { +pub(crate) fn home_dir() -> PathBuf { directories::BaseDirs::new() .map(|d| d.home_dir().to_path_buf()) .expect("could not determine home directory") } -pub fn config_dir() -> PathBuf { +pub(crate) fn config_dir() -> PathBuf { let config_dir = std::env::var("XDG_CONFIG_HOME").map_or_else(|_| home_dir().join(".config"), PathBuf::from); config_dir.join("atuin") } -pub fn data_dir() -> PathBuf { +pub(crate) fn data_dir() -> PathBuf { let data_dir = std::env::var("XDG_DATA_HOME") .map_or_else(|_| home_dir().join(".local").join("share"), PathBuf::from); data_dir.join("atuin") } -pub fn runtime_dir() -> PathBuf { +pub(crate) fn runtime_dir() -> PathBuf { std::env::var("XDG_RUNTIME_DIR").map_or_else(|_| data_dir(), PathBuf::from) } -pub fn logs_dir() -> PathBuf { +pub(crate) fn logs_dir() -> PathBuf { home_dir().join(".atuin").join("logs") } -pub fn dotfiles_cache_dir() -> PathBuf { +pub(crate) fn dotfiles_cache_dir() -> PathBuf { // In most cases, this will be ~/.local/share/atuin/dotfiles/cache let data_dir = std::env::var("XDG_DATA_HOME") .map_or_else(|_| home_dir().join(".local").join("share"), PathBuf::from); @@ -136,7 +136,7 @@ pub fn dotfiles_cache_dir() -> PathBuf { data_dir.join("atuin").join("dotfiles").join("cache") } -pub fn get_current_dir() -> String { +pub(crate) fn get_current_dir() -> String { // Prefer PWD environment variable over cwd if available to better support symbolic links match env::var("PWD") { Ok(v) => v, @@ -147,7 +147,7 @@ pub fn get_current_dir() -> String { } } -pub fn broken_symlink<P: Into<PathBuf>>(path: P) -> bool { +pub(crate) fn broken_symlink<P: Into<PathBuf>>(path: P) -> bool { let path = path.into(); path.is_symlink() && !path.exists() } @@ -158,7 +158,7 @@ pub fn broken_symlink<P: Into<PathBuf>>(path: P) -> bool { /// Intended to help prevent control characters being printed and interpreted by the terminal when /// printing history as well as to ensure the commands that appear in the interactive search /// reflect the actual command run rather than just the printable characters. -pub trait Escapable: AsRef<str> { +pub(crate) trait Escapable: AsRef<str> { fn escape_control(&self) -> Cow<'_, str> { if !self.as_ref().contains(|c: char| c.is_ascii_control()) { self.as_ref().into() @@ -182,7 +182,7 @@ pub trait Escapable: AsRef<str> { } } -pub fn unquote(s: &str) -> Result<String> { +pub(crate) fn unquote(s: &str) -> Result<String> { if s.chars().count() < 2 { return Err(eyre!("not enough chars")); } diff --git a/crates/turtle/src/atuin_daemon/client.rs b/crates/turtle/src/atuin_daemon/client.rs index 45ef19e9..a0a27741 100644 --- a/crates/turtle/src/atuin_daemon/client.rs +++ b/crates/turtle/src/atuin_daemon/client.rs @@ -33,12 +33,12 @@ use crate::atuin_daemon::semantic::{ semantic_client::SemanticClient as SemanticServiceClient, }; -pub struct HistoryClient { +pub(crate) struct HistoryClient { client: HistoryServiceClient<Channel>, } #[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum DaemonClientErrorKind { +pub(crate) enum DaemonClientErrorKind { Connect, Unavailable, Unimplemented, @@ -46,7 +46,7 @@ pub enum DaemonClientErrorKind { } #[must_use] -pub fn classify_error(error: &eyre::Report) -> DaemonClientErrorKind { +pub(crate) fn classify_error(error: &eyre::Report) -> DaemonClientErrorKind { for cause in error.chain() { if cause.downcast_ref::<tonic::transport::Error>().is_some() { return DaemonClientErrorKind::Connect; @@ -67,7 +67,7 @@ pub fn classify_error(error: &eyre::Report) -> DaemonClientErrorKind { // Wrap the grpc client impl HistoryClient { #[cfg(unix)] - pub async fn new(path: String) -> Result<Self> { + pub(crate) async fn new(path: String) -> Result<Self> { use eyre::Context; let log_path = path.clone(); @@ -92,7 +92,7 @@ impl HistoryClient { Ok(HistoryClient { client }) } - pub async fn start_history(&mut self, h: History) -> Result<StartHistoryReply> { + pub(crate) async fn start_history(&mut self, h: History) -> Result<StartHistoryReply> { let req = StartHistoryRequest { command: h.command, cwd: h.cwd, @@ -106,7 +106,7 @@ impl HistoryClient { Ok(self.client.start_history(req).await?.into_inner()) } - pub async fn end_history( + pub(crate) async fn end_history( &mut self, id: String, duration: u64, @@ -117,11 +117,11 @@ impl HistoryClient { Ok(self.client.end_history(req).await?.into_inner()) } - pub async fn status(&mut self) -> Result<StatusReply> { + pub(crate) async fn status(&mut self) -> Result<StatusReply> { Ok(self.client.status(StatusRequest {}).await?.into_inner()) } - pub async fn tail_history(&mut self) -> Result<tonic::Streaming<TailHistoryReply>> { + pub(crate) async fn tail_history(&mut self) -> Result<tonic::Streaming<TailHistoryReply>> { Ok(self .client .tail_history(TailHistoryRequest {}) @@ -129,19 +129,19 @@ impl HistoryClient { .into_inner()) } - pub async fn shutdown(&mut self) -> Result<bool> { + pub(crate) async fn shutdown(&mut self) -> Result<bool> { let resp = self.client.shutdown(ShutdownRequest {}).await?.into_inner(); Ok(resp.accepted) } } -pub struct SearchClient { +pub(crate) struct SearchClient { client: SearchServiceClient<Channel>, } impl SearchClient { #[cfg(unix)] - pub async fn new(path: String) -> Result<Self> { + pub(crate) async fn new(path: String) -> Result<Self> { let log_path = path.clone(); let channel = Endpoint::try_from("http://atuin_local_daemon:0")? .connect_with_connector(service_fn(move |_: Uri| { @@ -165,7 +165,7 @@ impl SearchClient { } #[instrument(skip_all, level = Level::TRACE, name = "daemon_client_search", fields(query = %query, query_id = query_id))] - pub async fn search( + pub(crate) async fn search( &mut self, query: String, query_id: u64, @@ -214,13 +214,13 @@ impl From<Context> for RpcSearchContext { } } -pub struct SemanticClient { +pub(crate) struct SemanticClient { client: SemanticServiceClient<Channel>, } impl SemanticClient { #[cfg(unix)] - pub async fn new(path: String) -> Result<Self> { + pub(crate) async fn new(path: String) -> Result<Self> { let log_path = path.clone(); let channel = Endpoint::try_from("http://atuin_local_daemon:0")? .connect_with_connector(service_fn(move |_: Uri| { @@ -244,11 +244,11 @@ impl SemanticClient { } #[cfg(unix)] - pub async fn from_settings(settings: &Settings) -> Result<Self> { + pub(crate) async fn from_settings(settings: &Settings) -> Result<Self> { Self::new(settings.daemon.socket_path.clone()).await } - pub async fn record_commands( + pub(crate) async fn record_commands( &mut self, captures: Vec<CommandCapture>, ) -> Result<RecordCommandsReply> { @@ -256,7 +256,7 @@ impl SemanticClient { Ok(self.client.record_commands(stream).await?.into_inner()) } - pub async fn command_output( + pub(crate) async fn command_output( &mut self, history_id: String, ranges: Vec<(i64, i64)>, @@ -280,14 +280,14 @@ impl SemanticClient { /// Client for the Control gRPC service. /// /// Used to inject events into a running daemon from external processes. -pub struct ControlClient { +pub(crate) struct ControlClient { client: ControlServiceClient<Channel>, } impl ControlClient { /// Connect to the daemon's control service. #[cfg(unix)] - pub async fn new(path: String) -> Result<Self> { + pub(crate) async fn new(path: String) -> Result<Self> { let log_path = path.clone(); let channel = Endpoint::try_from("http://atuin_local_daemon:0")? .connect_with_connector(service_fn(move |_: Uri| { @@ -312,12 +312,12 @@ impl ControlClient { /// Connect using settings. #[cfg(unix)] - pub async fn from_settings(settings: &Settings) -> Result<Self> { + pub(crate) async fn from_settings(settings: &Settings) -> Result<Self> { Self::new(settings.daemon.socket_path.clone()).await } /// Send an event to the daemon. - pub async fn send_event(&mut self, event: DaemonEvent) -> Result<()> { + pub(crate) async fn send_event(&mut self, event: DaemonEvent) -> Result<()> { let proto_event = daemon_event_to_proto(event); let request = SendEventRequest { event: Some(proto_event), @@ -377,7 +377,7 @@ fn daemon_event_to_proto( /// // Request immediate sync /// emit_event(DaemonEvent::ForceSync).await?; /// ``` -pub async fn emit_event(event: DaemonEvent) -> Result<()> { +pub(crate) async fn emit_event(event: DaemonEvent) -> Result<()> { emit_event_with_settings(event, None).await } @@ -385,7 +385,7 @@ pub async fn emit_event(event: DaemonEvent) -> Result<()> { /// /// If settings are not provided, they will be loaded from the default location. /// If the daemon isn't running, this will silently succeed. -pub async fn emit_event_with_settings( +pub(crate) async fn emit_event_with_settings( event: DaemonEvent, settings: Option<&Settings>, ) -> Result<()> { diff --git a/crates/turtle/src/atuin_daemon/components/history.rs b/crates/turtle/src/atuin_daemon/components/history.rs index 95d34b69..ec41977f 100644 --- a/crates/turtle/src/atuin_daemon/components/history.rs +++ b/crates/turtle/src/atuin_daemon/components/history.rs @@ -36,7 +36,7 @@ const DAEMON_PROTOCOL_VERSION: u32 = 1; /// - Saves completed commands to the database and record store /// - Emits history events for other components (e.g., search indexing) /// - Provides the History gRPC service -pub struct HistoryComponent { +pub(crate) struct HistoryComponent { inner: Arc<HistoryComponentInner>, } @@ -53,7 +53,7 @@ struct HistoryComponentInner { impl HistoryComponent { /// Create a new history component. - pub fn new() -> Self { + pub(crate) fn new() -> Self { Self { inner: Arc::new(HistoryComponentInner { running: DashMap::new(), @@ -66,7 +66,7 @@ impl HistoryComponent { /// Get the gRPC service for this component. /// /// This returns a tonic service that can be added to a gRPC server. - pub fn grpc_service(&self) -> HistoryServer<HistoryGrpcService> { + pub(crate) fn grpc_service(&self) -> HistoryServer<HistoryGrpcService> { HistoryServer::new(HistoryGrpcService { inner: self.inner.clone(), }) @@ -112,7 +112,7 @@ impl Component for HistoryComponent { /// The gRPC service implementation. /// /// This is a thin wrapper that delegates to the component's shared state. -pub struct HistoryGrpcService { +pub(crate) struct HistoryGrpcService { inner: Arc<HistoryComponentInner>, } diff --git a/crates/turtle/src/atuin_daemon/components/mod.rs b/crates/turtle/src/atuin_daemon/components/mod.rs index 447e31df..5a93fbc1 100644 --- a/crates/turtle/src/atuin_daemon/components/mod.rs +++ b/crates/turtle/src/atuin_daemon/components/mod.rs @@ -14,12 +14,12 @@ //! - [`semantic::SemanticComponent`]: In-memory semantic command captures //! - [`sync::SyncComponent`]: Cloud sync -pub mod history; -pub mod search; -pub mod semantic; -pub mod sync; +pub(crate) mod history; +pub(crate) mod search; +pub(crate) mod semantic; +pub(crate) mod sync; -pub use history::HistoryComponent; -pub use search::SearchComponent; -pub use semantic::SemanticComponent; -pub use sync::SyncComponent; +pub(crate) use history::HistoryComponent; +pub(crate) use search::SearchComponent; +pub(crate) use semantic::SemanticComponent; +pub(crate) use sync::SyncComponent; diff --git a/crates/turtle/src/atuin_daemon/components/search.rs b/crates/turtle/src/atuin_daemon/components/search.rs index 85191cff..17decdad 100644 --- a/crates/turtle/src/atuin_daemon/components/search.rs +++ b/crates/turtle/src/atuin_daemon/components/search.rs @@ -34,7 +34,7 @@ const FRECENCY_REFRESH_INTERVAL_SECS: u64 = 60; /// - Loads history from the database on startup /// - Updates the index when history events occur /// - Provides the Search gRPC service -pub struct SearchComponent { +pub(crate) struct SearchComponent { index: Arc<RwLock<SearchIndex>>, handle: tokio::sync::RwLock<Option<DaemonHandle>>, loader_handle: Option<tokio::task::JoinHandle<()>>, @@ -43,7 +43,7 @@ pub struct SearchComponent { impl SearchComponent { /// Create a new search component. - pub fn new() -> Self { + pub(crate) fn new() -> Self { Self { index: Arc::new(RwLock::new(SearchIndex::new())), handle: tokio::sync::RwLock::new(None), @@ -53,7 +53,7 @@ impl SearchComponent { } /// Get the gRPC service for this component. - pub fn grpc_service(&self) -> SearchServer<SearchGrpcService> { + pub(crate) fn grpc_service(&self) -> SearchServer<SearchGrpcService> { SearchServer::new(SearchGrpcService { index: self.index.clone(), }) @@ -273,7 +273,7 @@ impl Component for SearchComponent { } /// The gRPC service implementation. -pub struct SearchGrpcService { +pub(crate) struct SearchGrpcService { index: Arc<RwLock<SearchIndex>>, } @@ -395,7 +395,7 @@ fn convert_filter_mode( } #[cfg(windows)] -pub fn with_trailing_slash(s: &str) -> String { +pub(crate) fn with_trailing_slash(s: &str) -> String { if s.ends_with('\\') { s.to_string() } else { @@ -404,7 +404,7 @@ pub fn with_trailing_slash(s: &str) -> String { } #[cfg(not(windows))] -pub fn with_trailing_slash(s: &str) -> String { +pub(crate) fn with_trailing_slash(s: &str) -> String { if s.ends_with('/') { s.to_string() } else { diff --git a/crates/turtle/src/atuin_daemon/components/semantic.rs b/crates/turtle/src/atuin_daemon/components/semantic.rs index a42fd5cb..052c2d73 100644 --- a/crates/turtle/src/atuin_daemon/components/semantic.rs +++ b/crates/turtle/src/atuin_daemon/components/semantic.rs @@ -29,7 +29,7 @@ const MAX_BYTES_PER_SESSION: usize = 32 * 1024 * 1024; const MAX_PENDING_HISTORIES: usize = 128; /// Stores completed command captures and associates them with history events. -pub struct SemanticComponent { +pub(crate) struct SemanticComponent { inner: Arc<SemanticComponentInner>, } @@ -83,7 +83,7 @@ struct SemanticCommandRecord { } impl SemanticComponent { - pub fn new() -> Self { + pub(crate) fn new() -> Self { Self { inner: Arc::new(SemanticComponentInner { state: Mutex::new(SemanticState::default()), @@ -91,7 +91,7 @@ impl SemanticComponent { } } - pub fn grpc_service(&self) -> SemanticServer<SemanticGrpcService> { + pub(crate) fn grpc_service(&self) -> SemanticServer<SemanticGrpcService> { SemanticServer::new(SemanticGrpcService { inner: self.inner.clone(), }) @@ -452,7 +452,7 @@ impl Display for SessionId { } } -pub struct SemanticGrpcService { +pub(crate) struct SemanticGrpcService { inner: Arc<SemanticComponentInner>, } diff --git a/crates/turtle/src/atuin_daemon/components/sync.rs b/crates/turtle/src/atuin_daemon/components/sync.rs index c76fb71b..93d1024a 100644 --- a/crates/turtle/src/atuin_daemon/components/sync.rs +++ b/crates/turtle/src/atuin_daemon/components/sync.rs @@ -41,14 +41,14 @@ enum SyncState { /// - Implements exponential backoff on sync failures /// - Responds to ForceSync events for immediate sync /// - Emits SyncCompleted/SyncFailed events -pub struct SyncComponent { +pub(crate) struct SyncComponent { task_handle: Option<tokio::task::JoinHandle<()>>, command_tx: Option<mpsc::Sender<SyncCommand>>, } impl SyncComponent { /// Create a new sync component. - pub fn new() -> Self { + pub(crate) fn new() -> Self { Self { task_handle: None, command_tx: None, diff --git a/crates/turtle/src/atuin_daemon/control/mod.rs b/crates/turtle/src/atuin_daemon/control/mod.rs index afb29c57..23068519 100644 --- a/crates/turtle/src/atuin_daemon/control/mod.rs +++ b/crates/turtle/src/atuin_daemon/control/mod.rs @@ -9,4 +9,4 @@ mod service; tonic::include_proto!("control"); // Re-export the service -pub use service::ControlService; +pub(crate) use service::ControlService; diff --git a/crates/turtle/src/atuin_daemon/control/service.rs b/crates/turtle/src/atuin_daemon/control/service.rs index cb2ff74e..8061a3c2 100644 --- a/crates/turtle/src/atuin_daemon/control/service.rs +++ b/crates/turtle/src/atuin_daemon/control/service.rs @@ -18,18 +18,18 @@ use crate::atuin_daemon::{daemon::DaemonHandle, events::DaemonEvent}; /// /// This service is used by external processes to inject events into the daemon. /// It's not a component - it's part of the daemon's core infrastructure. -pub struct ControlService { +pub(crate) struct ControlService { handle: DaemonHandle, } impl ControlService { /// Create a new control service with the given daemon handle. - pub fn new(handle: DaemonHandle) -> Self { + pub(crate) fn new(handle: DaemonHandle) -> Self { Self { handle } } /// Get a tonic server for this service. - pub fn into_server(self) -> ControlServer<Self> { + pub(crate) fn into_server(self) -> ControlServer<Self> { ControlServer::new(self) } } diff --git a/crates/turtle/src/atuin_daemon/daemon.rs b/crates/turtle/src/atuin_daemon/daemon.rs index 77c0d8a5..3268548e 100644 --- a/crates/turtle/src/atuin_daemon/daemon.rs +++ b/crates/turtle/src/atuin_daemon/daemon.rs @@ -27,7 +27,7 @@ use crate::atuin_daemon::events::DaemonEvent; /// /// This contains all the resources that components and services need access to. /// The state is wrapped in an `Arc` and accessed via [`DaemonHandle`]. -pub struct DaemonState { +pub(crate) struct DaemonState { // Event bus event_tx: broadcast::Sender<DaemonEvent>, @@ -72,7 +72,7 @@ pub struct DaemonState { /// let history = handle.history_db().load(id).await?; /// ``` #[derive(Clone)] -pub struct DaemonHandle { +pub(crate) struct DaemonHandle { state: Arc<DaemonState>, } @@ -83,7 +83,7 @@ impl DaemonHandle { /// /// This is fire-and-forget - if no receivers are listening (which shouldn't /// happen in normal operation), the event is dropped silently. - pub fn emit(&self, event: DaemonEvent) { + pub(crate) fn emit(&self, event: DaemonEvent) { if let Err(e) = self.state.event_tx.send(event) { tracing::warn!("failed to emit event (no receivers?): {e}"); } @@ -94,12 +94,12 @@ impl DaemonHandle { /// Returns a receiver that will receive all events emitted after this call. /// Useful for components that need to listen for events outside of the /// normal `handle_event` callback flow. - pub fn subscribe(&self) -> broadcast::Receiver<DaemonEvent> { + pub(crate) fn subscribe(&self) -> broadcast::Receiver<DaemonEvent> { self.state.event_tx.subscribe() } /// Request graceful shutdown of the daemon. - pub fn shutdown(&self) { + pub(crate) fn shutdown(&self) { self.emit(DaemonEvent::ShutdownRequested); } @@ -109,7 +109,7 @@ impl DaemonHandle { /// /// This acquires a read lock on the settings. For most use cases, clone /// the settings if you need to hold onto them. - pub async fn settings(&self) -> tokio::sync::RwLockReadGuard<'_, Settings> { + pub(crate) async fn settings(&self) -> tokio::sync::RwLockReadGuard<'_, Settings> { self.state.settings.read().await } @@ -117,7 +117,7 @@ impl DaemonHandle { /// /// Components listening for `SettingsReloaded` can then re-read settings /// via `handle.settings()` to pick up the changes. - pub async fn reload_settings(&self) -> Result<()> { + pub(crate) async fn reload_settings(&self) -> Result<()> { let new_settings = Settings::new()?; self.apply_settings(new_settings).await; Ok(()) @@ -127,26 +127,26 @@ impl DaemonHandle { /// /// Use this when settings have already been loaded (e.g., from a file watcher) /// to avoid parsing the config file twice. - pub async fn apply_settings(&self, settings: Settings) { + pub(crate) async fn apply_settings(&self, settings: Settings) { *self.state.settings.write().await = settings; self.emit(DaemonEvent::SettingsReloaded); tracing::info!("settings applied"); } /// Get the encryption key. - pub fn encryption_key(&self) -> &[u8; 32] { + pub(crate) fn encryption_key(&self) -> &[u8; 32] { &self.state.encryption_key } // ---- Database ---- /// Get a reference to the history database. - pub fn history_db(&self) -> &HistoryDatabase { + pub(crate) fn history_db(&self) -> &HistoryDatabase { &self.state.history_db } /// Get a reference to the record store. - pub fn store(&self) -> &SqliteStore { + pub(crate) fn store(&self) -> &SqliteStore { &self.state.store } } @@ -181,7 +181,7 @@ impl std::fmt::Debug for DaemonHandle { /// # Example /// /// ```ignore -/// pub struct MyComponent { +/// pub(crate) struct MyComponent { /// handle: Option<DaemonHandle>, /// } /// @@ -213,7 +213,7 @@ impl std::fmt::Debug for DaemonHandle { /// } /// ``` #[tonic::async_trait] -pub trait Component: Send + Sync { +pub(crate) trait Component: Send + Sync { /// Human-readable name for logging and debugging. fn name(&self) -> &'static str; @@ -257,21 +257,21 @@ pub trait Component: Send + Sync { /// /// Events emitted during handling are queued and processed in subsequent /// iterations, ensuring the loop eventually drains. -pub struct Daemon { +pub(crate) struct Daemon { components: Vec<Box<dyn Component>>, handle: DaemonHandle, } impl Daemon { /// Create a new daemon builder. - pub fn builder(settings: Settings) -> DaemonBuilder { + pub(crate) fn builder(settings: Settings) -> DaemonBuilder { DaemonBuilder::new(settings) } /// Get a clone of the daemon handle. /// /// The handle can be used to emit events, access settings, etc. - pub fn handle(&self) -> DaemonHandle { + pub(crate) fn handle(&self) -> DaemonHandle { self.handle.clone() } @@ -279,7 +279,7 @@ impl Daemon { /// /// This must be called before `run_event_loop()`. It initializes all /// registered components with the daemon handle. - pub async fn start_components(&mut self) -> Result<()> { + pub(crate) async fn start_components(&mut self) -> Result<()> { for component in &mut self.components { tracing::info!(component = component.name(), "starting component"); component @@ -294,7 +294,7 @@ impl Daemon { /// /// This processes events until a ShutdownRequested event is received. /// Components must be started first via `start_components()`. - pub async fn run_event_loop(&mut self) -> Result<()> { + pub(crate) async fn run_event_loop(&mut self) -> Result<()> { let mut event_rx = self.handle.subscribe(); loop { match event_rx.recv().await { @@ -324,7 +324,7 @@ impl Daemon { /// Stop all components. /// /// This performs graceful shutdown of all components. - pub async fn stop_components(&mut self) { + pub(crate) async fn stop_components(&mut self) { for component in &mut self.components { tracing::info!(component = component.name(), "stopping component"); if let Err(e) = component.stop().await { @@ -342,7 +342,7 @@ impl Daemon { /// /// This is a convenience method that starts components, runs the event loop, /// and handles shutdown. It does not return until the daemon is shut down. - pub async fn run(mut self) -> Result<()> { + pub(crate) async fn run(mut self) -> Result<()> { self.start_components().await?; self.run_event_loop().await?; self.stop_components().await; @@ -383,7 +383,7 @@ impl Daemon { /// /// daemon.run().await?; /// ``` -pub struct DaemonBuilder { +pub(crate) struct DaemonBuilder { settings: Settings, store: Option<SqliteStore>, history_db: Option<HistoryDatabase>, @@ -392,7 +392,7 @@ pub struct DaemonBuilder { impl DaemonBuilder { /// Create a new daemon builder with the given settings. - pub fn new(settings: Settings) -> Self { + pub(crate) fn new(settings: Settings) -> Self { Self { settings, store: None, @@ -402,13 +402,13 @@ impl DaemonBuilder { } /// Set the record store. - pub fn store(mut self, store: SqliteStore) -> Self { + pub(crate) fn store(mut self, store: SqliteStore) -> Self { self.store = Some(store); self } /// Set the history database. - pub fn history_db(mut self, db: HistoryDatabase) -> Self { + pub(crate) fn history_db(mut self, db: HistoryDatabase) -> Self { self.history_db = Some(db); self } @@ -416,7 +416,7 @@ impl DaemonBuilder { /// Register a component. /// /// Components are started in registration order and stopped in reverse order. - pub fn component(mut self, component: impl Component + 'static) -> Self { + pub(crate) fn component(mut self, component: impl Component + 'static) -> Self { self.components.push(Box::new(component)); self } @@ -424,7 +424,7 @@ impl DaemonBuilder { /// Build the daemon. /// /// This loads the encryption key and creates the daemon state. - pub async fn build(self) -> Result<Daemon> { + pub(crate) async fn build(self) -> Result<Daemon> { let store = self.store.ok_or_else(|| eyre::eyre!("store is required"))?; let history_db = self .history_db diff --git a/crates/turtle/src/atuin_daemon/events.rs b/crates/turtle/src/atuin_daemon/events.rs index 9a398925..09369512 100644 --- a/crates/turtle/src/atuin_daemon/events.rs +++ b/crates/turtle/src/atuin_daemon/events.rs @@ -15,7 +15,7 @@ use crate::atuin_common::record::RecordId; /// Events are broadcast to all components. Each component decides which /// events it cares about in its `handle_event` implementation. #[derive(Debug, Clone)] -pub enum DaemonEvent { +pub(crate) enum DaemonEvent { // ---- History lifecycle ---- /// A command has started running. HistoryStarted(History), diff --git a/crates/turtle/src/atuin_daemon/mod.rs b/crates/turtle/src/atuin_daemon/mod.rs index aff33307..eac28f78 100644 --- a/crates/turtle/src/atuin_daemon/mod.rs +++ b/crates/turtle/src/atuin_daemon/mod.rs @@ -3,31 +3,31 @@ use crate::atuin_client::record::sqlite_store::SqliteStore; use crate::atuin_client::settings::{Settings, watcher::global_settings_watcher}; use eyre::Result; -pub mod client; -pub mod components; -pub mod control; -pub mod daemon; -pub mod events; -pub mod history; -pub mod search; -pub mod semantic; -pub mod server; +pub(crate) mod client; +pub(crate) mod components; +pub(crate) mod control; +pub(crate) mod daemon; +pub(crate) mod events; +pub(crate) mod history; +pub(crate) mod search; +pub(crate) mod semantic; +pub(crate) mod server; // Re-export core daemon types for convenience -pub use daemon::Daemon; -pub use events::DaemonEvent; +pub(crate) use daemon::Daemon; +pub(crate) use events::DaemonEvent; // Re-export components -pub use components::{HistoryComponent, SearchComponent, SemanticComponent, SyncComponent}; +pub(crate) use components::{HistoryComponent, SearchComponent, SemanticComponent, SyncComponent}; // Re-export client helpers -pub use client::SemanticClient; +pub(crate) use client::SemanticClient; /// Boot the daemon using the new component-based architecture. /// /// This creates a daemon with the standard components (history, search, sync), /// starts the gRPC server with their services, and runs the event loop. -pub async fn boot( +pub(crate) async fn boot( settings: Settings, store: SqliteStore, history_db: HistoryDatabase, diff --git a/crates/turtle/src/atuin_daemon/search/index.rs b/crates/turtle/src/atuin_daemon/search/index.rs index df627e1b..446d7992 100644 --- a/crates/turtle/src/atuin_daemon/search/index.rs +++ b/crates/turtle/src/atuin_daemon/search/index.rs @@ -38,16 +38,16 @@ fn format_uuid_bytes(bytes: &[u8; 16]) -> String { /// Pre-computed frecency data for O(1) lookup. #[derive(Debug, Clone, Default)] -pub struct FrecencyData { +pub(crate) struct FrecencyData { /// Total number of times this command was used. - pub count: u32, + pub(crate) count: u32, /// Most recent usage timestamp (unix seconds). - pub last_used: i64, + pub(crate) last_used: i64, } impl FrecencyData { /// Record a new usage of this command. - pub fn record_use(&mut self, timestamp: i64) { + pub(crate) fn record_use(&mut self, timestamp: i64) { self.count += 1; if timestamp > self.last_used { self.last_used = timestamp; @@ -66,7 +66,7 @@ impl FrecencyData { /// A multiplier of 0.0 disables that component, 1.0 is unchanged, 2.0 doubles weight. /// Values like 0.5 reduce weight by half, 1.5 increases by 50%, etc. #[instrument(level = tracing::Level::TRACE, name = "index_frecency_compute")] - pub fn compute(&self, now: i64, recency_mul: f64, frequency_mul: f64) -> u32 { + pub(crate) fn compute(&self, now: i64, recency_mul: f64, frequency_mul: f64) -> u32 { if self.count == 0 { return 0; } @@ -99,13 +99,13 @@ impl FrecencyData { } /// Data for a unique command. -pub struct CommandData { +pub(crate) struct CommandData { /// History ID of the most recent invocation (16-byte UUID). most_recent_id: [u8; 16], /// Timestamp of the most recent invocation. most_recent_timestamp: i64, /// Pre-computed global frecency. - pub global_frecency: FrecencyData, + pub(crate) global_frecency: FrecencyData, // Pre-computed indexes for O(1) filter lookups // Using HashSet instead of DashSet since CommandData lives inside DashMap (already synchronized) @@ -120,7 +120,7 @@ pub struct CommandData { impl CommandData { /// Create a new CommandData from a history entry. /// Returns None if the history entry has invalid UUIDs. - pub fn new(history: &History, interner: &ThreadedRodeo) -> Option<Self> { + pub(crate) fn new(history: &History, interner: &ThreadedRodeo) -> Option<Self> { let history_id = parse_uuid_bytes(&history.id.0)?; let session = parse_uuid_bytes(&history.session)?; let timestamp = history.timestamp.unix_timestamp(); @@ -152,7 +152,7 @@ impl CommandData { /// Add an invocation from a history entry. /// Returns false if the history entry has invalid UUIDs. - pub fn add_invocation(&mut self, history: &History, interner: &ThreadedRodeo) -> bool { + pub(crate) fn add_invocation(&mut self, history: &History, interner: &ThreadedRodeo) -> bool { let Some(history_id) = parse_uuid_bytes(&history.id.0) else { return false; }; @@ -181,13 +181,13 @@ impl CommandData { } /// Get the most recent history ID for this command. - pub fn most_recent_id(&self) -> String { + pub(crate) fn most_recent_id(&self) -> String { format_uuid_bytes(&self.most_recent_id) } /// Check if any invocation matches a directory filter (exact match). /// O(1) lookup using pre-computed index. - pub fn has_invocation_in_dir(&self, dir: &str, interner: &ThreadedRodeo) -> bool { + pub(crate) fn has_invocation_in_dir(&self, dir: &str, interner: &ThreadedRodeo) -> bool { interner .get(dir) .is_some_and(|spur| self.directories.contains(&spur)) @@ -195,7 +195,7 @@ impl CommandData { /// Check if any invocation matches a directory prefix (workspace/git root). /// O(n) where n = number of unique directories for this command. - pub fn has_invocation_in_workspace(&self, prefix: &str, interner: &ThreadedRodeo) -> bool { + pub(crate) fn has_invocation_in_workspace(&self, prefix: &str, interner: &ThreadedRodeo) -> bool { self.directories .iter() .any(|&spur| interner.resolve(&spur).starts_with(prefix)) @@ -203,7 +203,7 @@ impl CommandData { /// Check if any invocation matches a hostname. /// O(1) lookup using pre-computed index. - pub fn has_invocation_on_host(&self, hostname: &str, interner: &ThreadedRodeo) -> bool { + pub(crate) fn has_invocation_on_host(&self, hostname: &str, interner: &ThreadedRodeo) -> bool { interner .get(hostname) .is_some_and(|spur| self.hosts.contains(&spur)) @@ -211,14 +211,14 @@ impl CommandData { /// Check if any invocation matches a session. /// O(1) lookup using pre-computed index. - pub fn has_invocation_in_session(&self, session: &str) -> bool { + pub(crate) fn has_invocation_in_session(&self, session: &str) -> bool { parse_uuid_bytes(session).is_some_and(|bytes| self.sessions.contains(&bytes)) } } /// Filter mode for search queries. #[derive(Debug, Clone, PartialEq, Eq)] -pub enum IndexFilterMode { +pub(crate) enum IndexFilterMode { /// No filtering - search all commands. Global, /// Filter to commands run in a specific directory. @@ -233,11 +233,11 @@ pub enum IndexFilterMode { /// Context for search queries. #[derive(Debug, Clone, Default)] -pub struct QueryContext { - pub cwd: Option<String>, - pub git_root: Option<String>, - pub hostname: Option<String>, - pub session_id: Option<String>, +pub(crate) struct QueryContext { + pub(crate) cwd: Option<String>, + pub(crate) git_root: Option<String>, + pub(crate) hostname: Option<String>, + pub(crate) session_id: Option<String>, } /// Shareable frecency map: command -> frecency score. @@ -252,7 +252,7 @@ type FrecencyMap = Arc<HashMap<Arc<str>, u32>>; /// Global frecency is precomputed by a background task and used for scoring. /// If frecency data is not available, search still works but without frecency ranking; /// although this should never happen due to precomputing the frecency map. -pub struct SearchIndex { +pub(crate) struct SearchIndex { /// Map from command text to command data. /// Using DashMap for concurrent read/write access, wrapped in Arc for sharing with scorer. /// Keys are Arc<str> to enable zero-copy sharing with frecency_map. @@ -269,7 +269,7 @@ pub struct SearchIndex { impl SearchIndex { /// Create a new empty search index. - pub fn new() -> Self { + pub(crate) fn new() -> Self { let nucleo_config = atuin_nucleo::Config::DEFAULT; // Single column for command text let nucleo = Nucleo::<String>::new(nucleo_config, Arc::new(|| {}), None, 1); @@ -288,7 +288,7 @@ impl SearchIndex { /// /// If the command already exists, updates its invocation data. /// If it's a new command, adds it to both the map and Nucleo. - pub fn add_history(&self, history: &History) { + pub(crate) fn add_history(&self, history: &History) { if is_known_agent(&history.author) { return; } @@ -315,19 +315,19 @@ impl SearchIndex { } /// Add multiple history entries to the index. - pub fn add_histories(&self, histories: &[History]) { + pub(crate) fn add_histories(&self, histories: &[History]) { for history in histories { self.add_history(history); } } /// Get the number of unique commands in the index. - pub fn command_count(&self) -> usize { + pub(crate) fn command_count(&self) -> usize { self.commands.len() } /// Get the number of items in Nucleo (should match command_count). - pub async fn nucleo_item_count(&self) -> u32 { + pub(crate) async fn nucleo_item_count(&self) -> u32 { self.nucleo.read().await.snapshot().item_count() } @@ -336,7 +336,7 @@ impl SearchIndex { /// Returns a list of history IDs (most recent invocation per command). /// Uses precomputed global frecency for scoring if available. #[instrument(skip_all, level = tracing::Level::TRACE, name = "index_search", fields(query = %query))] - pub async fn search( + pub(crate) async fn search( &self, query: &str, filter_mode: IndexFilterMode, @@ -398,7 +398,7 @@ impl SearchIndex { /// - `frequency_score_multiplier`: Weight for frequency component /// - `frecency_score_multiplier`: Overall multiplier for final score #[instrument(skip_all, level = tracing::Level::DEBUG, name = "rebuild_frecency")] - pub async fn rebuild_frecency(&self, search_settings: &Search) { + pub(crate) async fn rebuild_frecency(&self, search_settings: &Search) { let now = OffsetDateTime::now_utc().unix_timestamp(); let mut frecency_map: HashMap<Arc<str>, u32> = HashMap::new(); diff --git a/crates/turtle/src/atuin_daemon/search/mod.rs b/crates/turtle/src/atuin_daemon/search/mod.rs index 4d261956..51b6c6cc 100644 --- a/crates/turtle/src/atuin_daemon/search/mod.rs +++ b/crates/turtle/src/atuin_daemon/search/mod.rs @@ -8,4 +8,4 @@ mod index; tonic::include_proto!("search"); // Re-export the service and index -pub use index::{IndexFilterMode, QueryContext, SearchIndex}; +pub(crate) use index::{IndexFilterMode, QueryContext, SearchIndex}; diff --git a/crates/turtle/src/atuin_daemon/server.rs b/crates/turtle/src/atuin_daemon/server.rs index 23b04342..65272d2a 100644 --- a/crates/turtle/src/atuin_daemon/server.rs +++ b/crates/turtle/src/atuin_daemon/server.rs @@ -16,7 +16,7 @@ use crate::atuin_client::settings::Settings; /// This starts the gRPC server in the background and returns immediately. /// The server will shut down when a ShutdownRequested event is received. #[cfg(unix)] -pub async fn run_grpc_server( +pub(crate) async fn run_grpc_server( settings: Settings, history_service: HistoryServer<HistoryGrpcService>, search_service: SearchServer<SearchGrpcService>, diff --git a/crates/turtle/src/atuin_history/mod.rs b/crates/turtle/src/atuin_history/mod.rs index e7b33916..41336a14 100644 --- a/crates/turtle/src/atuin_history/mod.rs +++ b/crates/turtle/src/atuin_history/mod.rs @@ -1,2 +1,2 @@ -pub mod sort; -pub mod stats; +pub(crate) mod sort; +pub(crate) mod stats; diff --git a/crates/turtle/src/atuin_history/sort.rs b/crates/turtle/src/atuin_history/sort.rs index b162c810..3143fa68 100644 --- a/crates/turtle/src/atuin_history/sort.rs +++ b/crates/turtle/src/atuin_history/sort.rs @@ -6,7 +6,7 @@ type ScoredHistory = (f64, History); // This sorting should be applicable to all search modes, and solve the more "obvious" issues // first. // Later on, we can pass in context and do some boosts there too. -pub fn sort(query: &str, input: Vec<History>) -> Vec<History> { +pub(crate) fn sort(query: &str, input: Vec<History>) -> Vec<History> { // This can totally be extended. We need to be _careful_ that it's not slow. // We also need to balance sorting db-side with sorting here. SQLite can do a lot, // but some things are just much easier/more doable in Rust. diff --git a/crates/turtle/src/atuin_history/stats.rs b/crates/turtle/src/atuin_history/stats.rs index e47d6c8e..12d1ffc5 100644 --- a/crates/turtle/src/atuin_history/stats.rs +++ b/crates/turtle/src/atuin_history/stats.rs @@ -7,10 +7,10 @@ use unicode_segmentation::UnicodeSegmentation; use crate::atuin_client::{history::History, settings::Settings, theme::Meaning, theme::Theme}; #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Stats { - pub total_commands: usize, - pub unique_commands: usize, - pub top: Vec<(Vec<String>, usize)>, +pub(crate) struct Stats { + pub(crate) total_commands: usize, + pub(crate) unique_commands: usize, + pub(crate) top: Vec<(Vec<String>, usize)>, } fn first_non_whitespace(s: &str) -> Option<usize> { @@ -162,7 +162,7 @@ fn strip_leading_env_vars(command: &str) -> &str { command[token_start_pos..].trim() } -pub fn pretty_print(stats: Stats, ngram_size: usize, theme: &Theme) { +pub(crate) fn pretty_print(stats: Stats, ngram_size: usize, theme: &Theme) { let max = stats.top.iter().map(|x| x.1).max().unwrap(); let num_pad = max.ilog10() as usize + 1; @@ -239,7 +239,7 @@ pub fn pretty_print(stats: Stats, ngram_size: usize, theme: &Theme) { println!("Unique commands: {}", stats.unique_commands); } -pub fn compute( +pub(crate) fn compute( settings: &Settings, history: &[History], count: usize, diff --git a/crates/turtle/src/atuin_pty_proxy/capture.rs b/crates/turtle/src/atuin_pty_proxy/capture.rs index 97ac9b8f..dbcb81fb 100644 --- a/crates/turtle/src/atuin_pty_proxy/capture.rs +++ b/crates/turtle/src/atuin_pty_proxy/capture.rs @@ -8,18 +8,18 @@ const SESSION_ID_PARAM: &str = "session_id"; const MAX_OUTPUT_CAPTURE_BYTES: usize = 1024 * 1024; #[derive(Debug, Clone, PartialEq, Eq)] -pub struct CommandCapture { - pub prompt: String, - pub command: String, - pub output: String, - pub exit_code: Option<i32>, - pub history_id: Option<String>, - pub session_id: Option<String>, - pub output_truncated: bool, - pub output_observed_bytes: u64, +pub(crate) struct CommandCapture { + pub(crate) prompt: String, + pub(crate) command: String, + pub(crate) output: String, + pub(crate) exit_code: Option<i32>, + pub(crate) history_id: Option<String>, + pub(crate) session_id: Option<String>, + pub(crate) output_truncated: bool, + pub(crate) output_observed_bytes: u64, } -pub type CommandCaptureSink = Box<dyn Fn(CommandCapture) + Send + 'static>; +pub(crate) type CommandCaptureSink = Box<dyn Fn(CommandCapture) + Send + 'static>; #[derive(Default)] struct CaptureBuffers { diff --git a/crates/turtle/src/atuin_pty_proxy/mod.rs b/crates/turtle/src/atuin_pty_proxy/mod.rs index 612943fa..e1d01c83 100644 --- a/crates/turtle/src/atuin_pty_proxy/mod.rs +++ b/crates/turtle/src/atuin_pty_proxy/mod.rs @@ -12,6 +12,6 @@ mod runtime; mod screen; #[cfg(unix)] -pub use capture::{CommandCapture, CommandCaptureSink}; +pub(crate) use capture::{CommandCapture, CommandCaptureSink}; #[cfg(unix)] -pub use pty_proxy::PtyProxy; +pub(crate) use pty_proxy::PtyProxy; diff --git a/crates/turtle/src/atuin_pty_proxy/osc133.rs b/crates/turtle/src/atuin_pty_proxy/osc133.rs index 5b70f0aa..d79166a6 100644 --- a/crates/turtle/src/atuin_pty_proxy/osc133.rs +++ b/crates/turtle/src/atuin_pty_proxy/osc133.rs @@ -25,7 +25,7 @@ /// Events emitted when an OSC 133 marker is detected. #[derive(Debug, Clone, PartialEq, Eq)] -pub enum Event { +pub(crate) enum Event { /// `ESC ] 133 ; A ST` — the shell is about to display its prompt. PromptStart, /// `ESC ] 133 ; B ST` — the prompt has ended; the user may type a command. @@ -41,7 +41,7 @@ pub enum Event { /// Parameters attached to an OSC 133 marker. #[derive(Debug, Default, Clone, PartialEq, Eq)] -pub struct Params { +pub(crate) struct Params { items: Vec<Param>, } @@ -49,13 +49,13 @@ impl Params { /// Iterate over all marker parameters in order. #[cfg(test)] #[inline] - pub fn iter(&self) -> impl Iterator<Item = &Param> { + pub(crate) fn iter(&self) -> impl Iterator<Item = &Param> { self.items.iter() } /// Return the value for the first `key=value` parameter with this key. #[inline] - pub fn get(&self, key: &str) -> Option<&str> { + pub(crate) fn get(&self, key: &str) -> Option<&str> { self.items.iter().find_map(|item| match item { Param::KeyValue { key: item_key, @@ -68,7 +68,7 @@ impl Params { /// A single OSC 133 marker parameter. #[derive(Debug, Clone, PartialEq, Eq)] -pub enum Param { +pub(crate) enum Param { /// A positional parameter without an equals sign. Value(String), /// A `key=value` parameter. @@ -77,29 +77,29 @@ pub enum Param { /// An OSC 133 event with its position in the most recent input chunk. #[derive(Debug, Clone, PartialEq, Eq)] -pub struct LocatedEvent { +pub(crate) struct LocatedEvent { /// The OSC 133 event that was parsed. - pub event: Event, + pub(crate) event: Event, /// Offset where this marker starts in the current chunk. /// /// If a marker started in an earlier [`Parser::push_located`] call, this is /// `0` in the chunk that completed the marker. - pub start_offset: usize, + pub(crate) start_offset: usize, /// Offset immediately after this marker's terminator in the current chunk. /// /// If a marker spans multiple [`Parser::push_located`] calls, this is still /// the offset in the chunk that completed the marker. - pub offset: usize, + pub(crate) offset: usize, /// The semantic zone after applying this event. - pub zone: Zone, + pub(crate) zone: Zone, /// Metadata parameters attached to this marker. - pub params: Params, + pub(crate) params: Params, } /// The current semantic zone as determined by the most recent OSC 133 marker. #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] #[expect(dead_code)] -pub enum Zone { +pub(crate) enum Zone { /// No marker seen yet, or after a `D` marker (between commands). #[default] Unknown, @@ -149,7 +149,7 @@ enum State { /// OSC 133 markers and reports [`Event`]s through a caller-supplied callback /// without modifying the data. It can sit transparently between a PTY reader /// and stdout. -pub struct Parser { +pub(crate) struct Parser { state: State, zone: Zone, sequence_start: Option<usize>, @@ -166,7 +166,7 @@ impl Default for Parser { impl Parser { /// Create a new parser in the initial (ground / unknown-zone) state. #[inline] - pub fn new() -> Self { + pub(crate) fn new() -> Self { Self { state: State::Ground, zone: Zone::Unknown, @@ -179,7 +179,7 @@ impl Parser { /// The current semantic zone based on markers seen so far. #[inline] #[expect(dead_code)] - pub fn zone(&self) -> Zone { + pub(crate) fn zone(&self) -> Zone { self.zone } @@ -197,7 +197,7 @@ impl Parser { /// caller — this method only *observes* the stream. #[cfg(test)] #[inline] - pub fn push(&mut self, data: &[u8], mut on_event: impl FnMut(Event)) { + pub(crate) fn push(&mut self, data: &[u8], mut on_event: impl FnMut(Event)) { self.push_located(data, |located| on_event(located.event)); } @@ -208,7 +208,7 @@ impl Parser { /// it suitable for callers that need to split the original chunk at marker /// boundaries. #[inline] - pub fn push_located(&mut self, data: &[u8], mut on_event: impl FnMut(LocatedEvent)) { + pub(crate) fn push_located(&mut self, data: &[u8], mut on_event: impl FnMut(LocatedEvent)) { self.sequence_start = (self.state != State::Ground).then_some(0); for (offset, &byte) in data.iter().enumerate() { diff --git a/crates/turtle/src/atuin_pty_proxy/pty_proxy.rs b/crates/turtle/src/atuin_pty_proxy/pty_proxy.rs index 8dde6f53..70a53318 100644 --- a/crates/turtle/src/atuin_pty_proxy/pty_proxy.rs +++ b/crates/turtle/src/atuin_pty_proxy/pty_proxy.rs @@ -3,7 +3,7 @@ use clap::{Args, Subcommand, ValueEnum}; use crate::atuin_pty_proxy::{CommandCaptureSink, runtime}; #[derive(Args, Debug)] -pub struct PtyProxy { +pub(crate) struct PtyProxy { /// Highlight OSC 133 prompt, input, output, and exit-code regions #[arg(long)] debug_osc133: bool, @@ -13,13 +13,13 @@ pub struct PtyProxy { } #[derive(Subcommand, Debug)] -pub enum Cmd { +pub(crate) enum Cmd { /// Print shell code to initialize atuin pty-proxy on shell startup Init(Init), } #[derive(Args, Debug)] -pub struct Init { +pub(crate) struct Init { /// Shell to generate init for. If omitted, attempt auto-detection #[arg(value_enum)] shell: Option<Shell>, @@ -54,7 +54,7 @@ impl RuntimeOptions { } impl PtyProxy { - pub fn run(self, command_capture_sink: Option<CommandCaptureSink>) { + pub(crate) fn run(self, command_capture_sink: Option<CommandCaptureSink>) { match self.cmd { Some(Cmd::Init(init)) => { if let Err(err) = init.run() { diff --git a/crates/turtle/src/atuin_server/handlers/health.rs b/crates/turtle/src/atuin_server/handlers/health.rs index aebd1e8f..d39f7aa5 100644 --- a/crates/turtle/src/atuin_server/handlers/health.rs +++ b/crates/turtle/src/atuin_server/handlers/health.rs @@ -3,11 +3,11 @@ use axum::{Json, http, response::IntoResponse}; use serde::Serialize; #[derive(Serialize)] -pub struct HealthResponse { - pub status: &'static str, +pub(crate) struct HealthResponse { + pub(crate) status: &'static str, } -pub async fn health_check() -> impl IntoResponse { +pub(crate) async fn health_check() -> impl IntoResponse { ( http::StatusCode::OK, Json(HealthResponse { status: "healthy" }), diff --git a/crates/turtle/src/atuin_server/handlers/history.rs b/crates/turtle/src/atuin_server/handlers/history.rs index 7f09161b..e5057bcb 100644 --- a/crates/turtle/src/atuin_server/handlers/history.rs +++ b/crates/turtle/src/atuin_server/handlers/history.rs @@ -23,7 +23,7 @@ use crate::atuin_server_database::{ use crate::atuin_common::api::*; #[instrument(skip_all, fields(user.id = user.id))] -pub async fn count<DB: Database>( +pub(crate) async fn count<DB: Database>( UserAuth(user): UserAuth, state: State<AppState<DB>>, ) -> Result<Json<CountResponse>, ErrorResponseStatus<'static>> { @@ -43,7 +43,7 @@ pub async fn count<DB: Database>( } #[instrument(skip_all, fields(user.id = user.id))] -pub async fn list<DB: Database>( +pub(crate) async fn list<DB: Database>( req: Query<SyncHistoryRequest>, UserAuth(user): UserAuth, headers: HeaderMap, @@ -101,7 +101,7 @@ pub async fn list<DB: Database>( } #[instrument(skip_all, fields(user.id = user.id))] -pub async fn delete<DB: Database>( +pub(crate) async fn delete<DB: Database>( UserAuth(user): UserAuth, state: State<AppState<DB>>, Json(req): Json<DeleteHistoryRequest>, @@ -123,7 +123,7 @@ pub async fn delete<DB: Database>( } #[instrument(skip_all, fields(user.id = user.id))] -pub async fn add<DB: Database>( +pub(crate) async fn add<DB: Database>( UserAuth(user): UserAuth, state: State<AppState<DB>>, Json(req): Json<Vec<AddHistoryRequest>>, @@ -174,7 +174,7 @@ pub async fn add<DB: Database>( } #[derive(serde::Deserialize, Debug)] -pub struct CalendarQuery { +pub(crate) struct CalendarQuery { #[serde(default = "serde_calendar::zero")] year: i32, #[serde(default = "serde_calendar::one")] @@ -187,21 +187,21 @@ pub struct CalendarQuery { mod serde_calendar { use time::UtcOffset; - pub fn zero() -> i32 { + pub(crate) fn zero() -> i32 { 0 } - pub fn one() -> u8 { + pub(crate) fn one() -> u8 { 1 } - pub fn utc() -> UtcOffset { + pub(crate) fn utc() -> UtcOffset { UtcOffset::UTC } } #[instrument(skip_all, fields(user.id = user.id))] -pub async fn calendar<DB: Database>( +pub(crate) async fn calendar<DB: Database>( Path(focus): Path<String>, Query(params): Query<CalendarQuery>, UserAuth(user): UserAuth, diff --git a/crates/turtle/src/atuin_server/handlers/mod.rs b/crates/turtle/src/atuin_server/handlers/mod.rs index 7722d03e..322324c4 100644 --- a/crates/turtle/src/atuin_server/handlers/mod.rs +++ b/crates/turtle/src/atuin_server/handlers/mod.rs @@ -4,16 +4,16 @@ use axum::{Json, extract::State, http, response::IntoResponse}; use crate::atuin_server::router::AppState; -pub mod health; -pub mod history; -pub mod record; -pub mod status; -pub mod user; -pub mod v0; +pub(crate) mod health; +pub(crate) mod history; +pub(crate) mod record; +pub(crate) mod status; +pub(crate) mod user; +pub(crate) mod v0; const VERSION: &str = env!("CARGO_PKG_VERSION"); -pub async fn index<DB: Database>(state: State<AppState<DB>>) -> Json<IndexResponse> { +pub(crate) async fn index<DB: Database>(state: State<AppState<DB>>) -> Json<IndexResponse> { let homage = r#""Through the fathomless deeps of space swims the star turtle Great A'Tuin, bearing on its back the four giant elephants who carry on their shoulders the mass of the Discworld." -- Sir Terry Pratchett"#; let version = state @@ -34,12 +34,12 @@ impl IntoResponse for ErrorResponseStatus<'_> { } } -pub struct ErrorResponseStatus<'a> { - pub error: ErrorResponse<'a>, - pub status: http::StatusCode, +pub(crate) struct ErrorResponseStatus<'a> { + pub(crate) error: ErrorResponse<'a>, + pub(crate) status: http::StatusCode, } -pub trait RespExt<'a> { +pub(crate) trait RespExt<'a> { fn with_status(self, status: http::StatusCode) -> ErrorResponseStatus<'a>; fn reply(reason: &'a str) -> Self; } diff --git a/crates/turtle/src/atuin_server/handlers/record.rs b/crates/turtle/src/atuin_server/handlers/record.rs index 63325606..39060423 100644 --- a/crates/turtle/src/atuin_server/handlers/record.rs +++ b/crates/turtle/src/atuin_server/handlers/record.rs @@ -8,7 +8,7 @@ use crate::atuin_server::router::UserAuth; use crate::atuin_common::record::{EncryptedData, Record}; #[instrument(skip_all, fields(user.id = user.id))] -pub async fn post(UserAuth(user): UserAuth) -> Result<(), ErrorResponseStatus<'static>> { +pub(crate) async fn post(UserAuth(user): UserAuth) -> Result<(), ErrorResponseStatus<'static>> { // anyone who has actually used the old record store (a very small number) will see this error // upon trying to sync. // 1. The status endpoint will say that the server has nothing @@ -24,7 +24,7 @@ pub async fn post(UserAuth(user): UserAuth) -> Result<(), ErrorResponseStatus<'s } #[instrument(skip_all, fields(user.id = user.id))] -pub async fn index(UserAuth(user): UserAuth) -> axum::response::Response { +pub(crate) async fn index(UserAuth(user): UserAuth) -> axum::response::Response { let ret = json!({ "hosts": {} }); @@ -33,7 +33,7 @@ pub async fn index(UserAuth(user): UserAuth) -> axum::response::Response { } #[instrument(skip_all, fields(user.id = user.id))] -pub async fn next( +pub(crate) async fn next( UserAuth(user): UserAuth, ) -> Result<Json<Vec<Record<EncryptedData>>>, ErrorResponseStatus<'static>> { let records = Vec::new(); diff --git a/crates/turtle/src/atuin_server/handlers/status.rs b/crates/turtle/src/atuin_server/handlers/status.rs index 0cf2ca1e..59be1e5c 100644 --- a/crates/turtle/src/atuin_server/handlers/status.rs +++ b/crates/turtle/src/atuin_server/handlers/status.rs @@ -10,7 +10,7 @@ use crate::atuin_common::api::*; const VERSION: &str = env!("CARGO_PKG_VERSION"); #[instrument(skip_all, fields(user.id = user.id))] -pub async fn status<DB: Database>( +pub(crate) async fn status<DB: Database>( UserAuth(user): UserAuth, state: State<AppState<DB>>, ) -> Result<Json<StatusResponse>, ErrorResponseStatus<'static>> { diff --git a/crates/turtle/src/atuin_server/handlers/user.rs b/crates/turtle/src/atuin_server/handlers/user.rs index 01b72202..7708d43e 100644 --- a/crates/turtle/src/atuin_server/handlers/user.rs +++ b/crates/turtle/src/atuin_server/handlers/user.rs @@ -29,7 +29,7 @@ use reqwest::header::CONTENT_TYPE; use crate::atuin_common::{api::*, utils::crypto_random_string}; -pub fn verify_str(hash: &str, password: &str) -> bool { +pub(crate) fn verify_str(hash: &str, password: &str) -> bool { let arg2 = Argon2::new(Algorithm::Argon2id, Version::V0x13, Params::default()); let Ok(hash) = PasswordHash::new(hash) else { return false; @@ -63,7 +63,7 @@ async fn send_register_hook(url: &str, username: String, registered: String) { } #[instrument(skip_all, fields(user.username = username.as_str()))] -pub async fn get<DB: Database>( +pub(crate) async fn get<DB: Database>( Path(username): Path<String>, state: State<AppState<DB>>, ) -> Result<Json<UserResponse>, ErrorResponseStatus<'static>> { @@ -87,7 +87,7 @@ pub async fn get<DB: Database>( } #[instrument(skip_all)] -pub async fn register<DB: Database>( +pub(crate) async fn register<DB: Database>( state: State<AppState<DB>>, Json(register): Json<RegisterRequest>, ) -> Result<Json<RegisterResponse>, ErrorResponseStatus<'static>> { @@ -163,7 +163,7 @@ pub async fn register<DB: Database>( } #[instrument(skip_all, fields(user.id = user.id))] -pub async fn delete<DB: Database>( +pub(crate) async fn delete<DB: Database>( UserAuth(user): UserAuth, state: State<AppState<DB>>, ) -> Result<Json<DeleteUserResponse>, ErrorResponseStatus<'static>> { @@ -183,7 +183,7 @@ pub async fn delete<DB: Database>( } #[instrument(skip_all, fields(user.id = user.id, change_password))] -pub async fn change_password<DB: Database>( +pub(crate) async fn change_password<DB: Database>( UserAuth(mut user): UserAuth, state: State<AppState<DB>>, Json(change_password): Json<ChangePasswordRequest>, @@ -213,7 +213,7 @@ pub async fn change_password<DB: Database>( } #[instrument(skip_all, fields(user.username = login.username.as_str()))] -pub async fn login<DB: Database>( +pub(crate) async fn login<DB: Database>( state: State<AppState<DB>>, login: Json<LoginRequest>, ) -> Result<Json<LoginResponse>, ErrorResponseStatus<'static>> { diff --git a/crates/turtle/src/atuin_server/handlers/v0/me.rs b/crates/turtle/src/atuin_server/handlers/v0/me.rs index a1e2db46..1f5f5016 100644 --- a/crates/turtle/src/atuin_server/handlers/v0/me.rs +++ b/crates/turtle/src/atuin_server/handlers/v0/me.rs @@ -7,7 +7,7 @@ use crate::atuin_server::router::UserAuth; use crate::atuin_common::api::*; #[instrument(skip_all, fields(user.id = user.id))] -pub async fn get( +pub(crate) async fn get( UserAuth(user): UserAuth, ) -> Result<Json<MeResponse>, ErrorResponseStatus<'static>> { Ok(Json(MeResponse { diff --git a/crates/turtle/src/atuin_server/handlers/v0/record.rs b/crates/turtle/src/atuin_server/handlers/v0/record.rs index 9b147a52..2cc09118 100644 --- a/crates/turtle/src/atuin_server/handlers/v0/record.rs +++ b/crates/turtle/src/atuin_server/handlers/v0/record.rs @@ -12,7 +12,7 @@ use crate::atuin_server_database::Database; use crate::atuin_common::record::{EncryptedData, HostId, Record, RecordIdx, RecordStatus}; #[instrument(skip_all, fields(user.id = user.id))] -pub async fn post<DB: Database>( +pub(crate) async fn post<DB: Database>( UserAuth(user): UserAuth, state: State<AppState<DB>>, Json(records): Json<Vec<Record<EncryptedData>>>, @@ -51,7 +51,7 @@ pub async fn post<DB: Database>( } #[instrument(skip_all, fields(user.id = user.id))] -pub async fn index<DB: Database>( +pub(crate) async fn index<DB: Database>( UserAuth(user): UserAuth, state: State<AppState<DB>>, ) -> Result<Json<RecordStatus>, ErrorResponseStatus<'static>> { @@ -76,7 +76,7 @@ pub async fn index<DB: Database>( } #[derive(Deserialize)] -pub struct NextParams { +pub(crate) struct NextParams { host: HostId, tag: String, start: Option<RecordIdx>, @@ -84,7 +84,7 @@ pub struct NextParams { } #[instrument(skip_all, fields(user.id = user.id))] -pub async fn next<DB: Database>( +pub(crate) async fn next<DB: Database>( params: Query<NextParams>, UserAuth(user): UserAuth, state: State<AppState<DB>>, diff --git a/crates/turtle/src/atuin_server/handlers/v0/store.rs b/crates/turtle/src/atuin_server/handlers/v0/store.rs index cd184546..8269d6b3 100644 --- a/crates/turtle/src/atuin_server/handlers/v0/store.rs +++ b/crates/turtle/src/atuin_server/handlers/v0/store.rs @@ -10,10 +10,10 @@ use crate::atuin_server::{ use crate::atuin_server_database::Database; #[derive(Deserialize)] -pub struct DeleteParams {} +pub(crate) struct DeleteParams {} #[instrument(skip_all, fields(user.id = user.id))] -pub async fn delete<DB: Database>( +pub(crate) async fn delete<DB: Database>( _params: Query<DeleteParams>, UserAuth(user): UserAuth, state: State<AppState<DB>>, diff --git a/crates/turtle/src/atuin_server/metrics.rs b/crates/turtle/src/atuin_server/metrics.rs index ebd0dd2d..7a9dc571 100644 --- a/crates/turtle/src/atuin_server/metrics.rs +++ b/crates/turtle/src/atuin_server/metrics.rs @@ -7,7 +7,7 @@ use axum::{ }; use metrics_exporter_prometheus::{Matcher, PrometheusBuilder, PrometheusHandle}; -pub fn setup_metrics_recorder() -> PrometheusHandle { +pub(crate) fn setup_metrics_recorder() -> PrometheusHandle { const EXPONENTIAL_SECONDS: &[f64] = &[ 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0, ]; @@ -25,7 +25,7 @@ pub fn setup_metrics_recorder() -> PrometheusHandle { /// Middleware to record some common HTTP metrics /// Generic over B to allow for arbitrary body types (eg Vec<u8>, Streams, a deserialized thing, etc) /// Someday tower-http might provide a metrics middleware: https://github.com/tower-rs/tower-http/issues/57 -pub async fn track_metrics(req: Request, next: Next) -> impl IntoResponse { +pub(crate) async fn track_metrics(req: Request, next: Next) -> impl IntoResponse { let start = Instant::now(); let path = match req.extensions().get::<MatchedPath>() { diff --git a/crates/turtle/src/atuin_server/mod.rs b/crates/turtle/src/atuin_server/mod.rs index bd0f2168..ad480e1d 100644 --- a/crates/turtle/src/atuin_server/mod.rs +++ b/crates/turtle/src/atuin_server/mod.rs @@ -10,9 +10,9 @@ mod metrics; mod router; mod utils; -pub use settings::Settings; +pub(crate) use settings::Settings; -pub mod settings; +pub(crate) mod settings; use tokio::net::TcpListener; use tokio::signal; @@ -31,7 +31,7 @@ async fn shutdown_signal() { eprintln!("Shutting down gracefully..."); } -pub async fn launch<Db: Database>(settings: Settings, addr: SocketAddr) -> Result<()> { +pub(crate) async fn launch<Db: Database>(settings: Settings, addr: SocketAddr) -> Result<()> { launch_with_tcp_listener::<Db>( settings, TcpListener::bind(addr) @@ -42,7 +42,7 @@ pub async fn launch<Db: Database>(settings: Settings, addr: SocketAddr) -> Resul .await } -pub async fn launch_with_tcp_listener<Db: Database>( +pub(crate) async fn launch_with_tcp_listener<Db: Database>( settings: Settings, listener: TcpListener, shutdown: impl Future<Output = ()> + Send + 'static, @@ -58,7 +58,7 @@ pub async fn launch_with_tcp_listener<Db: Database>( // The separate listener means it's much easier to ensure metrics are not accidentally exposed to // the public. -pub async fn launch_metrics_server(host: String, port: u16) -> Result<()> { +pub(crate) async fn launch_metrics_server(host: String, port: u16) -> Result<()> { let listener = TcpListener::bind((host, port)) .await .context("failed to bind metrics tcp")?; diff --git a/crates/turtle/src/atuin_server/router.rs b/crates/turtle/src/atuin_server/router.rs index 11a16148..ed3d1e55 100644 --- a/crates/turtle/src/atuin_server/router.rs +++ b/crates/turtle/src/atuin_server/router.rs @@ -19,7 +19,7 @@ use crate::atuin_server::{ }; use crate::atuin_server_database::{Database, DbError, models::User}; -pub struct UserAuth(pub User); +pub(crate) struct UserAuth(pub(crate) User); impl<DB: Send + Sync> FromRequestParts<AppState<DB>> for UserAuth where @@ -101,12 +101,12 @@ async fn semver(request: Request, next: Next) -> Response { } #[derive(Clone)] -pub struct AppState<DB: Database> { - pub database: DB, - pub settings: Settings, +pub(crate) struct AppState<DB: Database> { + pub(crate) database: DB, + pub(crate) settings: Settings, } -pub fn router<DB: Database>(database: DB, settings: Settings) -> Router { +pub(crate) fn router<DB: Database>(database: DB, settings: Settings) -> Router { let mut routes = Router::new() .route("/", get(handlers::index)) .route("/healthz", get(handlers::health::health_check)); diff --git a/crates/turtle/src/atuin_server/settings.rs b/crates/turtle/src/atuin_server/settings.rs index 2bce0dac..1d0ac2d0 100644 --- a/crates/turtle/src/atuin_server/settings.rs +++ b/crates/turtle/src/atuin_server/settings.rs @@ -7,11 +7,11 @@ use fs_err::{File, create_dir_all}; use serde::{Deserialize, Serialize}; #[derive(Clone, Debug, Deserialize, Serialize)] -pub struct Metrics { +pub(crate) struct Metrics { #[serde(alias = "enabled")] - pub enable: bool, - pub host: String, - pub port: u16, + pub(crate) enable: bool, + pub(crate) host: String, + pub(crate) port: u16, } impl Default for Metrics { @@ -25,35 +25,35 @@ impl Default for Metrics { } #[derive(Clone, Debug, Deserialize, Serialize)] -pub struct Settings { - pub host: String, - pub port: u16, - pub path: String, - pub open_registration: bool, - pub max_history_length: usize, - pub max_record_size: usize, - pub page_size: i64, - pub register_webhook_url: Option<String>, - pub register_webhook_username: String, - pub metrics: Metrics, +pub(crate) struct Settings { + pub(crate) host: String, + pub(crate) port: u16, + pub(crate) path: String, + pub(crate) open_registration: bool, + pub(crate) max_history_length: usize, + pub(crate) max_record_size: usize, + pub(crate) page_size: i64, + pub(crate) register_webhook_url: Option<String>, + pub(crate) register_webhook_username: String, + pub(crate) metrics: Metrics, /// Enable legacy sync v1 routes (history-based sync) /// Set to false to use only the newer record-based sync - pub sync_v1_enabled: bool, + pub(crate) sync_v1_enabled: bool, /// Advertise a version that is not what we are _actually_ running /// Many clients compare their version with api.atuin.sh, and if they differ, notify the user /// that an update is available. /// Now that we take beta releases, we should be able to advertise a different version to avoid /// notifying users when the server runs something that is not a stable release. - pub fake_version: Option<String>, + pub(crate) fake_version: Option<String>, #[serde(flatten)] - pub db_settings: DbSettings, + pub(crate) db_settings: DbSettings, } impl Settings { - pub fn new() -> Result<Self> { + pub(crate) fn new() -> Result<Self> { let mut config_file = if let Ok(p) = std::env::var("ATUIN_CONFIG_DIR") { PathBuf::from(p) } else { diff --git a/crates/turtle/src/atuin_server/utils.rs b/crates/turtle/src/atuin_server/utils.rs index 12e9ac1b..cceef3ed 100644 --- a/crates/turtle/src/atuin_server/utils.rs +++ b/crates/turtle/src/atuin_server/utils.rs @@ -1,7 +1,7 @@ use eyre::Result; use semver::{Version, VersionReq}; -pub fn client_version_min(user_agent: &str, req: &str) -> Result<bool> { +pub(crate) fn client_version_min(user_agent: &str, req: &str) -> Result<bool> { if user_agent.is_empty() { return Ok(false); } diff --git a/crates/turtle/src/atuin_server_database/calendar.rs b/crates/turtle/src/atuin_server_database/calendar.rs index 2229667b..f1c78262 100644 --- a/crates/turtle/src/atuin_server_database/calendar.rs +++ b/crates/turtle/src/atuin_server_database/calendar.rs @@ -3,16 +3,16 @@ use serde::{Deserialize, Serialize}; use time::Month; -pub enum TimePeriod { +pub(crate) enum TimePeriod { Year, Month { year: i32 }, Day { year: i32, month: Month }, } #[derive(Debug, Serialize, Deserialize)] -pub struct TimePeriodInfo { - pub count: u64, +pub(crate) struct TimePeriodInfo { + pub(crate) count: u64, // TODO: Use this for merkle tree magic - pub hash: String, + pub(crate) hash: String, } diff --git a/crates/turtle/src/atuin_server_database/mod.rs b/crates/turtle/src/atuin_server_database/mod.rs index 91077b84..e4672bb0 100644 --- a/crates/turtle/src/atuin_server_database/mod.rs +++ b/crates/turtle/src/atuin_server_database/mod.rs @@ -1,5 +1,5 @@ -pub mod calendar; -pub mod models; +pub(crate) mod calendar; +pub(crate) mod models; use std::{ collections::HashMap, @@ -18,7 +18,7 @@ use time::{Date, Duration, Month, OffsetDateTime, PrimitiveDateTime, Time, UtcOf use tracing::instrument; #[derive(Debug)] -pub enum DbError { +pub(crate) enum DbError { NotFound, Other(eyre::Report), } @@ -52,24 +52,24 @@ impl From<sqlx::Error> for DbError { impl std::error::Error for DbError {} -pub type DbResult<T> = Result<T, DbError>; +pub(crate) type DbResult<T> = Result<T, DbError>; #[derive(Debug, PartialEq)] -pub enum DbType { +pub(crate) enum DbType { Postgres, Sqlite, Unknown, } #[derive(Clone, Deserialize, Serialize)] -pub struct DbSettings { - pub db_uri: String, +pub(crate) struct DbSettings { + pub(crate) db_uri: String, /// Optional URI for read replicas. If set, read-only queries will use this connection. - pub read_db_uri: Option<String>, + pub(crate) read_db_uri: Option<String>, } impl DbSettings { - pub fn db_type(&self) -> DbType { + pub(crate) fn db_type(&self) -> DbType { if self.db_uri.starts_with("postgres://") || self.db_uri.starts_with("postgresql://") { DbType::Postgres } else if self.db_uri.starts_with("sqlite://") { @@ -109,7 +109,7 @@ impl Debug for DbSettings { } #[async_trait] -pub trait Database: Sized + Clone + Send + Sync + 'static { +pub(crate) trait Database: Sized + Clone + Send + Sync + 'static { async fn new(settings: &DbSettings) -> DbResult<Self>; async fn get_session(&self, token: &str) -> DbResult<Session>; @@ -238,7 +238,7 @@ pub trait Database: Sized + Clone + Send + Sync + 'static { } } -pub fn into_utc(x: OffsetDateTime) -> PrimitiveDateTime { +pub(crate) fn into_utc(x: OffsetDateTime) -> PrimitiveDateTime { let x = x.to_offset(UtcOffset::UTC); PrimitiveDateTime::new(x.date(), x.time()) } diff --git a/crates/turtle/src/atuin_server_database/models.rs b/crates/turtle/src/atuin_server_database/models.rs index b71a9bc9..e47d614d 100644 --- a/crates/turtle/src/atuin_server_database/models.rs +++ b/crates/turtle/src/atuin_server_database/models.rs @@ -1,52 +1,52 @@ use time::OffsetDateTime; -pub struct History { - pub id: i64, - pub client_id: String, // a client generated ID - pub user_id: i64, - pub hostname: String, - pub timestamp: OffsetDateTime, +pub(crate) struct History { + pub(crate) id: i64, + pub(crate) client_id: String, // a client generated ID + pub(crate) user_id: i64, + pub(crate) hostname: String, + pub(crate) timestamp: OffsetDateTime, /// All the data we have about this command, encrypted. /// /// Currently this is an encrypted msgpack object, but this may change in the future. - pub data: String, + pub(crate) data: String, - pub created_at: OffsetDateTime, + pub(crate) created_at: OffsetDateTime, } -pub struct NewHistory { - pub client_id: String, - pub user_id: i64, - pub hostname: String, - pub timestamp: OffsetDateTime, +pub(crate) struct NewHistory { + pub(crate) client_id: String, + pub(crate) user_id: i64, + pub(crate) hostname: String, + pub(crate) timestamp: OffsetDateTime, /// All the data we have about this command, encrypted. /// /// Currently this is an encrypted msgpack object, but this may change in the future. - pub data: String, + pub(crate) data: String, } -pub struct User { - pub id: i64, - pub username: String, - pub email: String, - pub password: String, +pub(crate) struct User { + pub(crate) id: i64, + pub(crate) username: String, + pub(crate) email: String, + pub(crate) password: String, } -pub struct Session { - pub id: i64, - pub user_id: i64, - pub token: String, +pub(crate) struct Session { + pub(crate) id: i64, + pub(crate) user_id: i64, + pub(crate) token: String, } -pub struct NewUser { - pub username: String, - pub email: String, - pub password: String, +pub(crate) struct NewUser { + pub(crate) username: String, + pub(crate) email: String, + pub(crate) password: String, } -pub struct NewSession { - pub user_id: i64, - pub token: String, +pub(crate) struct NewSession { + pub(crate) user_id: i64, + pub(crate) token: String, } diff --git a/crates/turtle/src/atuin_server_postgres/mod.rs b/crates/turtle/src/atuin_server_postgres/mod.rs index 96bcb7c2..e06f8721 100644 --- a/crates/turtle/src/atuin_server_postgres/mod.rs +++ b/crates/turtle/src/atuin_server_postgres/mod.rs @@ -23,7 +23,7 @@ mod wrappers; const MIN_PG_VERSION: u32 = 14; #[derive(Clone)] -pub struct Postgres { +pub(crate) struct Postgres { pool: sqlx::Pool<sqlx::postgres::Postgres>, /// Optional read replica pool for read-only queries read_pool: Option<sqlx::Pool<sqlx::postgres::Postgres>>, diff --git a/crates/turtle/src/atuin_server_postgres/wrappers.rs b/crates/turtle/src/atuin_server_postgres/wrappers.rs index 214b255d..ba7a9435 100644 --- a/crates/turtle/src/atuin_server_postgres/wrappers.rs +++ b/crates/turtle/src/atuin_server_postgres/wrappers.rs @@ -4,10 +4,10 @@ use crate::atuin_server_database::models::{History, Session, User}; use sqlx::{Row, postgres::PgRow}; use time::PrimitiveDateTime; -pub struct DbUser(pub User); -pub struct DbSession(pub Session); -pub struct DbHistory(pub History); -pub struct DbRecord(pub Record<EncryptedData>); +pub(crate) struct DbUser(pub(crate) User); +pub(crate) struct DbSession(pub(crate) Session); +pub(crate) struct DbHistory(pub(crate) History); +pub(crate) struct DbRecord(pub(crate) Record<EncryptedData>); impl<'a> FromRow<'a, PgRow> for DbUser { fn from_row(row: &'a PgRow) -> Result<Self> { diff --git a/crates/turtle/src/atuin_server_sqlite/mod.rs b/crates/turtle/src/atuin_server_sqlite/mod.rs index bc40db3f..b1de511d 100644 --- a/crates/turtle/src/atuin_server_sqlite/mod.rs +++ b/crates/turtle/src/atuin_server_sqlite/mod.rs @@ -18,7 +18,7 @@ use wrappers::{DbHistory, DbRecord, DbSession, DbUser}; mod wrappers; #[derive(Clone)] -pub struct Sqlite { +pub(crate) struct Sqlite { pool: sqlx::Pool<sqlx::sqlite::Sqlite>, } diff --git a/crates/turtle/src/atuin_server_sqlite/wrappers.rs b/crates/turtle/src/atuin_server_sqlite/wrappers.rs index 5aa7a982..e7380bce 100644 --- a/crates/turtle/src/atuin_server_sqlite/wrappers.rs +++ b/crates/turtle/src/atuin_server_sqlite/wrappers.rs @@ -3,10 +3,10 @@ use crate::atuin_common::record::{EncryptedData, Host, Record}; use crate::atuin_server_database::models::{History, Session, User}; use sqlx::{Row, sqlite::SqliteRow}; -pub struct DbUser(pub User); -pub struct DbSession(pub Session); -pub struct DbHistory(pub History); -pub struct DbRecord(pub Record<EncryptedData>); +pub(crate) struct DbUser(pub(crate) User); +pub(crate) struct DbSession(pub(crate) Session); +pub(crate) struct DbHistory(pub(crate) History); +pub(crate) struct DbRecord(pub(crate) Record<EncryptedData>); impl<'a> FromRow<'a, SqliteRow> for DbUser { fn from_row(row: &'a SqliteRow) -> Result<Self> { diff --git a/crates/turtle/src/command/client.rs b/crates/turtle/src/command/client.rs index 20d85303..15df60f8 100644 --- a/crates/turtle/src/command/client.rs +++ b/crates/turtle/src/command/client.rs @@ -65,7 +65,7 @@ mod wrapped; #[derive(Subcommand, Debug)] #[command(infer_subcommands = true)] -pub enum Cmd { +pub(crate) enum Cmd { /// Setup Atuin features #[command()] Setup, @@ -129,7 +129,7 @@ pub enum Cmd { } impl Cmd { - pub fn run(self) -> Result<()> { + pub(crate) fn run(self) -> Result<()> { // Daemonize before creating the async runtime – fork() inside a live // tokio runtime corrupts its internal state. #[cfg(all(unix, feature = "daemon"))] diff --git a/crates/turtle/src/command/client/account.rs b/crates/turtle/src/command/client/account.rs index 898f1ac4..f2ceb10b 100644 --- a/crates/turtle/src/command/client/account.rs +++ b/crates/turtle/src/command/client/account.rs @@ -4,20 +4,20 @@ use eyre::Result; use crate::atuin_client::record::sqlite_store::SqliteStore; use crate::atuin_client::settings::Settings; -pub mod change_password; -pub mod delete; -pub mod login; -pub mod logout; -pub mod register; +pub(crate) mod change_password; +pub(crate) mod delete; +pub(crate) mod login; +pub(crate) mod logout; +pub(crate) mod register; #[derive(Args, Debug)] -pub struct Cmd { +pub(crate) struct Cmd { #[command(subcommand)] command: Commands, } #[derive(Subcommand, Debug)] -pub enum Commands { +pub(crate) enum Commands { /// Login to the configured server Login(login::Cmd), @@ -35,7 +35,7 @@ pub enum Commands { } impl Cmd { - pub async fn run(self, settings: Settings, store: SqliteStore) -> Result<()> { + pub(crate) async fn run(self, settings: Settings, store: SqliteStore) -> Result<()> { match self.command { Commands::Login(l) => l.run(&settings, &store).await, Commands::Register(r) => r.run(&settings).await, diff --git a/crates/turtle/src/command/client/account/change_password.rs b/crates/turtle/src/command/client/account/change_password.rs index 6112b0df..f7f7eb69 100644 --- a/crates/turtle/src/command/client/account/change_password.rs +++ b/crates/turtle/src/command/client/account/change_password.rs @@ -8,20 +8,20 @@ use crate::atuin_client::{ use rpassword::prompt_password; #[derive(Parser, Debug)] -pub struct Cmd { +pub(crate) struct Cmd { #[clap(long, short)] - pub current_password: Option<String>, + pub(crate) current_password: Option<String>, #[clap(long, short)] - pub new_password: Option<String>, + pub(crate) new_password: Option<String>, /// The two-factor authentication code for your account, if any #[clap(long, short)] - pub totp_code: Option<String>, + pub(crate) totp_code: Option<String>, } impl Cmd { - pub async fn run(&self, settings: &Settings) -> Result<()> { + pub(crate) async fn run(&self, settings: &Settings) -> Result<()> { if !settings.logged_in().await? { bail!("You are not logged in"); } diff --git a/crates/turtle/src/command/client/account/delete.rs b/crates/turtle/src/command/client/account/delete.rs index bcb40bc3..1c96cb4a 100644 --- a/crates/turtle/src/command/client/account/delete.rs +++ b/crates/turtle/src/command/client/account/delete.rs @@ -8,17 +8,17 @@ use eyre::{Result, bail}; use super::login::{or_user_input, read_user_password}; #[derive(Parser, Debug)] -pub struct Cmd { +pub(crate) struct Cmd { #[clap(long, short)] - pub password: Option<String>, + pub(crate) password: Option<String>, /// The two-factor authentication code for your account, if any #[clap(long, short)] - pub totp_code: Option<String>, + pub(crate) totp_code: Option<String>, } impl Cmd { - pub async fn run(&self, settings: &Settings) -> Result<()> { + pub(crate) async fn run(&self, settings: &Settings) -> Result<()> { if !settings.logged_in().await? { bail!("You are not logged in"); } diff --git a/crates/turtle/src/command/client/account/login.rs b/crates/turtle/src/command/client/account/login.rs index 0c5b66f5..1ec0293a 100644 --- a/crates/turtle/src/command/client/account/login.rs +++ b/crates/turtle/src/command/client/account/login.rs @@ -15,23 +15,23 @@ use crate::atuin_client::{ use rpassword::prompt_password; #[derive(Parser, Debug)] -pub struct Cmd { +pub(crate) struct Cmd { #[clap(long, short)] - pub username: Option<String>, + pub(crate) username: Option<String>, #[clap(long, short)] - pub password: Option<String>, + pub(crate) password: Option<String>, /// The encryption key for your account #[clap(long, short)] - pub key: Option<String>, + pub(crate) key: Option<String>, /// The two-factor authentication code for your account, if any #[clap(long, short)] - pub totp_code: Option<String>, + pub(crate) totp_code: Option<String>, #[clap(long, hide = true)] - pub from_registration: bool, + pub(crate) from_registration: bool, } fn get_input() -> Result<String> { @@ -41,7 +41,7 @@ fn get_input() -> Result<String> { } impl Cmd { - pub async fn run(&self, settings: &Settings, store: &SqliteStore) -> Result<()> { + pub(crate) async fn run(&self, settings: &Settings, store: &SqliteStore) -> Result<()> { match settings.resolve_sync_auth().await { SyncAuth::Legacy { .. } => { println!("You are logged in to your sync server."); diff --git a/crates/turtle/src/command/client/account/logout.rs b/crates/turtle/src/command/client/account/logout.rs index 6150a52b..5708e34c 100644 --- a/crates/turtle/src/command/client/account/logout.rs +++ b/crates/turtle/src/command/client/account/logout.rs @@ -1,5 +1,5 @@ use eyre::Result; -pub async fn run() -> Result<()> { +pub(crate) async fn run() -> Result<()> { crate::atuin_client::logout::logout().await } diff --git a/crates/turtle/src/command/client/account/register.rs b/crates/turtle/src/command/client/account/register.rs index 548c2739..64fb9f8d 100644 --- a/crates/turtle/src/command/client/account/register.rs +++ b/crates/turtle/src/command/client/account/register.rs @@ -5,19 +5,19 @@ use super::login::or_user_input; use crate::atuin_client::settings::{Settings, SyncAuth}; #[derive(Parser, Debug)] -pub struct Cmd { +pub(crate) struct Cmd { #[clap(long, short)] - pub username: Option<String>, + pub(crate) username: Option<String>, #[clap(long, short)] - pub password: Option<String>, + pub(crate) password: Option<String>, #[clap(long, short)] - pub email: Option<String>, + pub(crate) email: Option<String>, } impl Cmd { - pub async fn run(&self, settings: &Settings) -> Result<()> { + pub(crate) async fn run(&self, settings: &Settings) -> Result<()> { match settings.resolve_sync_auth().await { SyncAuth::Legacy { .. } => { println!("You are already logged in."); diff --git a/crates/turtle/src/command/client/config.rs b/crates/turtle/src/command/client/config.rs index 1597a8d6..73d1c35e 100644 --- a/crates/turtle/src/command/client/config.rs +++ b/crates/turtle/src/command/client/config.rs @@ -5,7 +5,7 @@ use toml_edit::{Document, DocumentMut, Item, Table, TableLike, Value}; #[derive(Subcommand, Debug)] #[command(infer_subcommands = true)] -pub enum Cmd { +pub(crate) enum Cmd { /// Get a configuration value from your config.toml file /// or after defaults and overrides are applied #[command()] @@ -24,7 +24,7 @@ pub enum Cmd { } impl Cmd { - pub async fn run(self, settings: &Settings) -> Result<()> { + pub(crate) async fn run(self, settings: &Settings) -> Result<()> { match self { Self::Get(get) => get.run(settings).await, Self::Set(set) => set.run(settings).await, @@ -36,21 +36,21 @@ impl Cmd { /// Get a configuration value from your config.toml file, /// or optionally the effective value after defaults and overrides are applied. #[derive(Args, Debug)] -pub struct GetCmd { +pub(crate) struct GetCmd { /// The configuration key to get - pub key: String, + pub(crate) key: String, /// Print the value after defaults and overrides are applied #[arg(long, short)] - pub resolved: bool, + pub(crate) resolved: bool, /// Print both the config file value and the resolved value #[arg(long, short)] - pub verbose: bool, + pub(crate) verbose: bool, } impl GetCmd { - pub async fn run(&self, _settings: &Settings) -> Result<()> { + pub(crate) async fn run(&self, _settings: &Settings) -> Result<()> { let key = self.key.trim(); if key.is_empty() || key.contains(char::is_whitespace) { eyre::bail!("Config key must be non-empty and must not contain whitespace"); @@ -116,20 +116,20 @@ impl GetCmd { } #[derive(Args, Debug)] -pub struct SetCmd { +pub(crate) struct SetCmd { /// The configuration key to set - pub key: String, + pub(crate) key: String, /// The value to set - pub value: String, + pub(crate) value: String, /// Store value as an explicit type #[arg(long = "type", short, value_enum, default_value_t = ValueType::Auto, value_name = "TYPE")] - pub the_type: ValueType, + pub(crate) the_type: ValueType, } #[derive(ValueEnum, Debug, Clone, PartialEq, Eq)] -pub enum ValueType { +pub(crate) enum ValueType { /// Automatically determine the type of the value Auto, /// Store value as a string @@ -143,7 +143,7 @@ pub enum ValueType { } impl SetCmd { - pub async fn run(self, _settings: &Settings) -> Result<()> { + pub(crate) async fn run(self, _settings: &Settings) -> Result<()> { let key = self.key.trim(); if key.is_empty() || key.contains(char::is_whitespace) { eyre::bail!("Config key must be non-empty and must not contain whitespace"); @@ -213,13 +213,13 @@ impl SetCmd { } #[derive(Args, Debug)] -pub struct PrintCmd { +pub(crate) struct PrintCmd { /// Print the value of a specific key and all its children - pub key: Option<String>, + pub(crate) key: Option<String>, } impl PrintCmd { - pub async fn run(&self, _settings: &Settings) -> Result<()> { + pub(crate) async fn run(&self, _settings: &Settings) -> Result<()> { let config_file = Settings::get_config_path()?; let config_str = tokio::fs::read_to_string(&config_file).await?; let doc = config_str.parse::<Document<_>>()?; diff --git a/crates/turtle/src/command/client/daemon.rs b/crates/turtle/src/command/client/daemon.rs index 2ee9b759..2fb090aa 100644 --- a/crates/turtle/src/command/client/daemon.rs +++ b/crates/turtle/src/command/client/daemon.rs @@ -21,7 +21,7 @@ use fs4::fs_std::FileExt; use tokio::time::sleep; #[derive(clap::Args, Debug)] -pub struct Cmd { +pub(crate) struct Cmd { /// Internal flag for daemonization #[arg(long, hide = true)] daemonize: bool, @@ -36,7 +36,7 @@ pub struct Cmd { #[derive(Subcommand, Debug)] #[command(infer_subcommands = true)] -pub enum SubCmd { +pub(crate) enum SubCmd { /// Start the daemon server Start { #[arg(long, hide = true)] @@ -65,7 +65,7 @@ impl Cmd { /// Returns `true` when the process should daemonize before creating the /// async runtime or opening any database connections. #[cfg(unix)] - pub fn should_daemonize(&self) -> bool { + pub(crate) fn should_daemonize(&self) -> bool { match &self.subcmd { Some(SubCmd::Start { daemonize, .. }) => *daemonize, None => self.daemonize, @@ -74,7 +74,7 @@ impl Cmd { } /// Returns `true` when logs should also be written to the console. - pub fn show_logs(&self) -> bool { + pub(crate) fn show_logs(&self) -> bool { match &self.subcmd { Some(SubCmd::Start { show_logs, .. }) => *show_logs, None => self.show_logs, @@ -82,7 +82,7 @@ impl Cmd { } } - pub async fn run( + pub(crate) async fn run( self, settings: Settings, store: SqliteStore, @@ -350,7 +350,7 @@ fn ensure_autostart_supported(settings: &Settings) -> Result<()> { /// process and wait for it to become ready. /// /// Returns an error if the daemon could not be started. -pub async fn ensure_daemon_running(settings: &Settings) -> Result<()> { +pub(crate) async fn ensure_daemon_running(settings: &Settings) -> Result<()> { ensure_autostart_supported(settings)?; let timeout = startup_timeout(settings); @@ -404,7 +404,7 @@ fn ensure_reply_compatible(settings: &Settings, version: &str, protocol: u32) -> bail!("{message}. Enable `daemon.autostart = true` or restart the daemon manually"); } -pub async fn start_history(settings: &Settings, history: History) -> Result<String> { +pub(crate) async fn start_history(settings: &Settings, history: History) -> Result<String> { match async { connect_client(settings) .await? @@ -438,7 +438,7 @@ pub async fn start_history(settings: &Settings, history: History) -> Result<Stri Ok(resp.id) } -pub async fn end_history(settings: &Settings, id: String, duration: u64, exit: i64) -> Result<()> { +pub(crate) async fn end_history(settings: &Settings, id: String, duration: u64, exit: i64) -> Result<()> { match async { connect_client(settings) .await? @@ -482,7 +482,7 @@ pub async fn end_history(settings: &Settings, id: String, duration: u64, exit: i /// If the daemon is not reachable and `daemon.autostart` is enabled, this /// will start the daemon and retry the event. If the daemon cannot be /// started or the retry fails, a warning is printed to stderr. -pub async fn emit_event(settings: &Settings, event: DaemonEvent) { +pub(crate) async fn emit_event(settings: &Settings, event: DaemonEvent) { // Try to connect and send match ControlClient::from_settings(settings).await { Ok(mut client) => { @@ -516,7 +516,7 @@ pub async fn emit_event(settings: &Settings, event: DaemonEvent) { } } -pub async fn tail_client(settings: &Settings) -> Result<HistoryClient> { +pub(crate) async fn tail_client(settings: &Settings) -> Result<HistoryClient> { match probe(settings).await { Probe::Ready(client) => return Ok(client), Probe::NeedsRestart(reason) if !settings.daemon.autostart => { @@ -619,7 +619,7 @@ async fn restart_cmd(settings: &Settings) -> Result<()> { /// runtime or opening database connections, since `fork()` inside an async /// runtime corrupts its internal state. #[cfg(unix)] -pub fn daemonize_current_process() -> Result<()> { +pub(crate) fn daemonize_current_process() -> Result<()> { let cwd = std::env::current_dir().wrap_err("could not determine current directory for daemon")?; diff --git a/crates/turtle/src/command/client/default_config.rs b/crates/turtle/src/command/client/default_config.rs index e8cc15f9..4b03c909 100644 --- a/crates/turtle/src/command/client/default_config.rs +++ b/crates/turtle/src/command/client/default_config.rs @@ -1,4 +1,4 @@ -pub fn run() { +pub(crate) fn run() { // TODO(@bpeetz): Re-add the default settings option back (Settings::example_config()) <2026-06-11> println!("TODO"); } diff --git a/crates/turtle/src/command/client/doctor.rs b/crates/turtle/src/command/client/doctor.rs index 09fa6e77..1ed90c47 100644 --- a/crates/turtle/src/command/client/doctor.rs +++ b/crates/turtle/src/command/client/doctor.rs @@ -13,17 +13,17 @@ use sysinfo::{Disks, System, get_current_pid}; #[derive(Debug, Serialize)] struct ShellInfo { - pub name: String, + pub(crate) name: String, // best-effort, not supported on all OSes - pub default: String, + pub(crate) default: String, // Detect some shell plugins that the user has installed. // I'm just going to start with preexec/blesh - pub plugins: Vec<String>, + pub(crate) plugins: Vec<String>, // The preexec framework used in the current session, if Atuin is loaded. - pub preexec: Option<String>, + pub(crate) preexec: Option<String>, } impl ShellInfo { @@ -86,7 +86,7 @@ impl ShellInfo { .map(|_| "blesh".to_string()) } - pub fn plugins(shell: &str, shell_process: &sysinfo::Process) -> Vec<String> { + pub(crate) fn plugins(shell: &str, shell_process: &sysinfo::Process) -> Vec<String> { // consider a different detection approach if there are plugins // that don't set shell vars @@ -167,7 +167,7 @@ impl ShellInfo { .collect() } - pub fn new() -> Self { + pub(crate) fn new() -> Self { // TODO: rework to use crate::atuin_common::Shell let sys = System::new_all(); @@ -199,22 +199,22 @@ impl ShellInfo { #[derive(Debug, Serialize)] struct DiskInfo { - pub name: String, - pub filesystem: String, + pub(crate) name: String, + pub(crate) filesystem: String, } #[derive(Debug, Serialize)] struct SystemInfo { - pub os: String, + pub(crate) os: String, - pub arch: String, + pub(crate) arch: String, - pub version: String, - pub disks: Vec<DiskInfo>, + pub(crate) version: String, + pub(crate) disks: Vec<DiskInfo>, } impl SystemInfo { - pub fn new() -> Self { + pub(crate) fn new() -> Self { let disks = Disks::new_with_refreshed_list(); let disks = disks .list() @@ -236,14 +236,14 @@ impl SystemInfo { #[derive(Debug, Serialize)] struct SyncInfo { - pub auth_state: String, - pub auto_sync: bool, + pub(crate) auth_state: String, + pub(crate) auto_sync: bool, - pub last_sync: String, + pub(crate) last_sync: String, } impl SyncInfo { - pub async fn new(settings: &Settings) -> Self { + pub(crate) async fn new(settings: &Settings) -> Self { // Build auth state description from raw token state without calling // resolve_sync_auth(), which has side effects (token migration cleanup) // that a diagnostic command should not trigger. @@ -277,7 +277,7 @@ struct SettingPaths { } impl SettingPaths { - pub fn new(settings: &Settings) -> Self { + pub(crate) fn new(settings: &Settings) -> Self { Self { db: settings.db_path.clone(), record_store: settings.record_store_path.clone(), @@ -285,7 +285,7 @@ impl SettingPaths { } } - pub fn verify(&self) { + pub(crate) fn verify(&self) { let paths = vec![ ("ATUIN_DB_PATH", &self.db), ("ATUIN_RECORD_STORE", &self.record_store), @@ -304,21 +304,21 @@ impl SettingPaths { #[derive(Debug, Serialize)] struct AtuinInfo { - pub version: String, - pub commit: String, + pub(crate) version: String, + pub(crate) commit: String, /// Whether the main Atuin sync server is in use /// I'm just calling it Atuin Cloud for lack of a better name atm - pub sync: Option<SyncInfo>, + pub(crate) sync: Option<SyncInfo>, - pub sqlite_version: String, + pub(crate) sqlite_version: String, #[serde(skip)] // probably unnecessary to expose this - pub setting_paths: SettingPaths, + pub(crate) setting_paths: SettingPaths, } impl AtuinInfo { - pub async fn new(settings: &Settings) -> Self { + pub(crate) async fn new(settings: &Settings) -> Self { let logged_in = settings.logged_in().await.unwrap_or(false); let sync = if logged_in { @@ -347,13 +347,13 @@ impl AtuinInfo { #[derive(Debug, Serialize)] struct DoctorDump { - pub atuin: AtuinInfo, - pub shell: ShellInfo, - pub system: SystemInfo, + pub(crate) atuin: AtuinInfo, + pub(crate) shell: ShellInfo, + pub(crate) system: SystemInfo, } impl DoctorDump { - pub async fn new(settings: &Settings) -> Self { + pub(crate) async fn new(settings: &Settings) -> Self { Self { atuin: AtuinInfo::new(settings).await, shell: ShellInfo::new(), @@ -396,7 +396,7 @@ fn checks(info: &DoctorDump) { } } -pub async fn run(settings: &Settings) -> Result<()> { +pub(crate) async fn run(settings: &Settings) -> Result<()> { println!("{}", "Atuin Doctor".bold()); println!("Checking for diagnostics"); let dump = DoctorDump::new(settings).await; diff --git a/crates/turtle/src/command/client/history.rs b/crates/turtle/src/command/client/history.rs index 0c61392c..e533759b 100644 --- a/crates/turtle/src/command/client/history.rs +++ b/crates/turtle/src/command/client/history.rs @@ -43,7 +43,7 @@ use super::search::format_duration_into; #[derive(Subcommand, Debug)] #[command(infer_subcommands = true)] -pub enum Cmd { +pub(crate) enum Cmd { /// Begins a new command in the history Start { /// Collects the command from the `ATUIN_COMMAND_LINE` environment variable, @@ -163,14 +163,14 @@ pub enum Cmd { } #[derive(Clone, Copy, Debug)] -pub enum ListMode { +pub(crate) enum ListMode { Human, CmdOnly, Regular, } impl ListMode { - pub const fn from_flags(human: bool, cmd_only: bool) -> Self { + pub(crate) const fn from_flags(human: bool, cmd_only: bool) -> Self { if human { ListMode::Human } else if cmd_only { @@ -182,7 +182,7 @@ impl ListMode { } #[expect(clippy::cast_sign_loss)] -pub fn print_list( +pub(crate) fn print_list( h: &[History], list_mode: ListMode, format: Option<&str>, @@ -1078,7 +1078,7 @@ impl Cmd { } #[expect(clippy::too_many_lines)] - pub async fn run(self, settings: &Settings) -> Result<()> { + pub(crate) async fn run(self, settings: &Settings) -> Result<()> { match self { Self::Start { cmd_env, diff --git a/crates/turtle/src/command/client/import.rs b/crates/turtle/src/command/client/import.rs index 363e6405..3ec524d2 100644 --- a/crates/turtle/src/command/client/import.rs +++ b/crates/turtle/src/command/client/import.rs @@ -17,7 +17,7 @@ use crate::atuin_client::{ #[derive(Parser, Debug)] #[command(infer_subcommands = true)] -pub enum Cmd { +pub(crate) enum Cmd { /// Import history for the current shell Auto, @@ -49,7 +49,7 @@ const BATCH_SIZE: usize = 100; impl Cmd { #[expect(clippy::cognitive_complexity)] - pub async fn run<DB: Database>(&self, db: &DB) -> Result<()> { + pub(crate) async fn run<DB: Database>(&self, db: &DB) -> Result<()> { println!(" Atuin "); println!("======================"); println!(" \u{1f30d} "); @@ -135,7 +135,7 @@ impl Cmd { } } -pub struct HistoryImporter<'db, DB: Database> { +pub(crate) struct HistoryImporter<'db, DB: Database> { pb: ProgressBar, buf: Vec<History>, db: &'db DB, diff --git a/crates/turtle/src/command/client/info.rs b/crates/turtle/src/command/client/info.rs index ee24c419..fc944987 100644 --- a/crates/turtle/src/command/client/info.rs +++ b/crates/turtle/src/command/client/info.rs @@ -2,7 +2,7 @@ use crate::atuin_client::settings::Settings; use crate::{SHA, VERSION};
-pub fn run(settings: &Settings) {
+pub(crate) fn run(settings: &Settings) {
let config = crate::atuin_common::utils::config_dir();
let mut config_file = config.clone();
config_file.push("config.toml");
diff --git a/crates/turtle/src/command/client/init.rs b/crates/turtle/src/command/client/init.rs index bf9747bb..776100cf 100644 --- a/crates/turtle/src/command/client/init.rs +++ b/crates/turtle/src/command/client/init.rs @@ -8,7 +8,7 @@ mod xonsh; mod zsh; #[derive(Parser, Debug)] -pub struct Cmd { +pub(crate) struct Cmd { shell: Shell, /// Disable the binding of CTRL-R to atuin @@ -27,7 +27,7 @@ pub struct Cmd { #[derive(Clone, Copy, ValueEnum, Debug)] #[value(rename_all = "lower")] #[expect(clippy::enum_variant_names, clippy::doc_markdown)] -pub enum Shell { +pub(crate) enum Shell { /// Zsh setup Zsh, /// Bash setup @@ -115,7 +115,7 @@ $env.config = ( } } - pub fn run(self, settings: &Settings) { + pub(crate) fn run(self, settings: &Settings) { if !settings.paths_ok() { eprintln!( "Atuin settings paths are broken. Disabling atuin shell hooks. Run `atuin doctor` to diagnose." diff --git a/crates/turtle/src/command/client/init/bash.rs b/crates/turtle/src/command/client/init/bash.rs index fd17e37e..a5f6eb8d 100644 --- a/crates/turtle/src/command/client/init/bash.rs +++ b/crates/turtle/src/command/client/init/bash.rs @@ -9,7 +9,7 @@ fn print_tmux_config(tmux: &Tmux) { } } -pub fn init_static(disable_up_arrow: bool, disable_ctrl_r: bool, tmux: &Tmux) { +pub(crate) fn init_static(disable_up_arrow: bool, disable_ctrl_r: bool, tmux: &Tmux) { let base = include_str!("../../../shell/atuin.bash"); let (bind_ctrl_r, bind_up_arrow) = if std::env::var("ATUIN_NOBIND").is_ok() { diff --git a/crates/turtle/src/command/client/init/fish.rs b/crates/turtle/src/command/client/init/fish.rs index 8a046bfa..27325bcd 100644 --- a/crates/turtle/src/command/client/init/fish.rs +++ b/crates/turtle/src/command/client/init/fish.rs @@ -35,7 +35,7 @@ fn print_bindings( println!("{indent}end"); } -pub fn init_static(disable_up_arrow: bool, disable_ctrl_r: bool, tmux: &Tmux) { +pub(crate) fn init_static(disable_up_arrow: bool, disable_ctrl_r: bool, tmux: &Tmux) { let indent = " ".repeat(4); let base = include_str!("../../../shell/atuin.fish"); diff --git a/crates/turtle/src/command/client/init/powershell.rs b/crates/turtle/src/command/client/init/powershell.rs index 10c0c461..8deb9a3b 100644 --- a/crates/turtle/src/command/client/init/powershell.rs +++ b/crates/turtle/src/command/client/init/powershell.rs @@ -1,6 +1,6 @@ use crate::atuin_client::settings::Tmux; -pub fn init_static(disable_up_arrow: bool, disable_ctrl_r: bool, _tmux: &Tmux) { +pub(crate) fn init_static(disable_up_arrow: bool, disable_ctrl_r: bool, _tmux: &Tmux) { let base = include_str!("../../../shell/atuin.ps1"); let (bind_ctrl_r, bind_up_arrow) = if std::env::var("ATUIN_NOBIND").is_ok() { diff --git a/crates/turtle/src/command/client/init/xonsh.rs b/crates/turtle/src/command/client/init/xonsh.rs index a17d85d8..ccb71880 100644 --- a/crates/turtle/src/command/client/init/xonsh.rs +++ b/crates/turtle/src/command/client/init/xonsh.rs @@ -1,6 +1,6 @@ use crate::atuin_client::settings::Tmux; -pub fn init_static(disable_up_arrow: bool, disable_ctrl_r: bool, _tmux: &Tmux) { +pub(crate) fn init_static(disable_up_arrow: bool, disable_ctrl_r: bool, _tmux: &Tmux) { let base = include_str!("../../../shell/atuin.xsh"); let (bind_ctrl_r, bind_up_arrow) = if std::env::var("ATUIN_NOBIND").is_ok() { diff --git a/crates/turtle/src/command/client/init/zsh.rs b/crates/turtle/src/command/client/init/zsh.rs index 38c3086b..60d0138f 100644 --- a/crates/turtle/src/command/client/init/zsh.rs +++ b/crates/turtle/src/command/client/init/zsh.rs @@ -9,7 +9,7 @@ fn print_tmux_config(tmux: &Tmux) { } } -pub fn init_static(disable_up_arrow: bool, disable_ctrl_r: bool, tmux: &Tmux) { +pub(crate) fn init_static(disable_up_arrow: bool, disable_ctrl_r: bool, tmux: &Tmux) { let base = include_str!("../../../shell/atuin.zsh"); print_tmux_config(tmux); diff --git a/crates/turtle/src/command/client/search.rs b/crates/turtle/src/command/client/search.rs index 4a2114d5..72112084 100644 --- a/crates/turtle/src/command/client/search.rs +++ b/crates/turtle/src/command/client/search.rs @@ -23,13 +23,13 @@ mod engines; mod history_list; mod inspector; mod interactive; -pub mod keybindings; +pub(crate) mod keybindings; -pub use duration::format_duration_into; +pub(crate) use duration::format_duration_into; #[expect(clippy::struct_excessive_bools, clippy::struct_field_names)] #[derive(Parser, Debug)] -pub struct Cmd { +pub(crate) struct Cmd { /// Filter search result by directory #[arg(long, short)] cwd: Option<String>, @@ -147,7 +147,7 @@ pub struct Cmd { impl Cmd { /// Returns true if this search command will run in interactive (TUI) mode - pub fn is_interactive(&self) -> bool { + pub(crate) fn is_interactive(&self) -> bool { self.interactive } @@ -155,7 +155,7 @@ impl Cmd { // clippy: now it has too many lines // me: I'll do it later OKAY #[expect(clippy::too_many_lines)] - pub async fn run( + pub(crate) async fn run( self, db: impl Database, settings: &mut Settings, diff --git a/crates/turtle/src/command/client/search/cursor.rs b/crates/turtle/src/command/client/search/cursor.rs index 84f94082..a69f1359 100644 --- a/crates/turtle/src/command/client/search/cursor.rs +++ b/crates/turtle/src/command/client/search/cursor.rs @@ -1,6 +1,6 @@ use crate::atuin_client::settings::WordJumpMode; -pub struct Cursor { +pub(crate) struct Cursor { source: String, index: usize, } @@ -11,7 +11,7 @@ impl From<String> for Cursor { } } -pub struct WordJumper<'a> { +pub(crate) struct WordJumper<'a> { word_chars: &'a str, word_jump_mode: WordJumpMode, } @@ -93,25 +93,25 @@ impl WordJumper<'_> { } impl Cursor { - pub fn as_str(&self) -> &str { + pub(crate) fn as_str(&self) -> &str { self.source.as_str() } - pub fn into_inner(self) -> String { + pub(crate) fn into_inner(self) -> String { self.source } /// Returns the string before the cursor - pub fn substring(&self) -> &str { + pub(crate) fn substring(&self) -> &str { &self.source[..self.index] } /// Returns the currently selected [`char`] - pub fn char(&self) -> Option<char> { + pub(crate) fn char(&self) -> Option<char> { self.source[self.index..].chars().next() } - pub fn right(&mut self) { + pub(crate) fn right(&mut self) { if self.index < self.source.len() { loop { self.index += 1; @@ -122,7 +122,7 @@ impl Cursor { } } - pub fn left(&mut self) -> bool { + pub(crate) fn left(&mut self) -> bool { if self.index > 0 { loop { self.index -= 1; @@ -135,7 +135,7 @@ impl Cursor { } } - pub fn next_word(&mut self, word_chars: &str, word_jump_mode: WordJumpMode) { + pub(crate) fn next_word(&mut self, word_chars: &str, word_jump_mode: WordJumpMode) { let word_jumper = WordJumper { word_chars, word_jump_mode, @@ -143,7 +143,7 @@ impl Cursor { self.index = word_jumper.get_next_word_pos(&self.source, self.index); } - pub fn prev_word(&mut self, word_chars: &str, word_jump_mode: WordJumpMode) { + pub(crate) fn prev_word(&mut self, word_chars: &str, word_jump_mode: WordJumpMode) { let word_jumper = WordJumper { word_chars, word_jump_mode, @@ -156,7 +156,7 @@ impl Cursor { /// If cursor is in the middle of a word, moves to the end of that word. /// If cursor is at the end of a word (or on whitespace), moves to the /// end of the next word. - pub fn word_end(&mut self, word_chars: &str) { + pub(crate) fn word_end(&mut self, word_chars: &str) { let len = self.source.len(); if self.index >= len { return; @@ -213,12 +213,12 @@ impl Cursor { self.index = chars.iter().take(char_idx).map(|c| c.len_utf8()).sum(); } - pub fn insert(&mut self, c: char) { + pub(crate) fn insert(&mut self, c: char) { self.source.insert(self.index, c); self.index += c.len_utf8(); } - pub fn remove(&mut self) -> Option<char> { + pub(crate) fn remove(&mut self) -> Option<char> { if self.index < self.source.len() { Some(self.source.remove(self.index)) } else { @@ -226,7 +226,7 @@ impl Cursor { } } - pub fn remove_next_word(&mut self, word_chars: &str, word_jump_mode: WordJumpMode) { + pub(crate) fn remove_next_word(&mut self, word_chars: &str, word_jump_mode: WordJumpMode) { let word_jumper = WordJumper { word_chars, word_jump_mode, @@ -235,7 +235,7 @@ impl Cursor { self.source.replace_range(self.index..next_index, ""); } - pub fn remove_prev_word(&mut self, word_chars: &str, word_jump_mode: WordJumpMode) { + pub(crate) fn remove_prev_word(&mut self, word_chars: &str, word_jump_mode: WordJumpMode) { let word_jumper = WordJumper { word_chars, word_jump_mode, @@ -245,34 +245,34 @@ impl Cursor { self.index = next_index; } - pub fn back(&mut self) -> Option<char> { + pub(crate) fn back(&mut self) -> Option<char> { if self.left() { self.remove() } else { None } } - pub fn clear(&mut self) { + pub(crate) fn clear(&mut self) { self.source.clear(); self.index = 0; } - pub fn clear_to_start(&mut self) { + pub(crate) fn clear_to_start(&mut self) { self.source.replace_range(..self.index, ""); self.index = 0; } - pub fn clear_to_end(&mut self) { + pub(crate) fn clear_to_end(&mut self) { self.source.replace_range(self.index.., ""); self.index = self.source.len(); } - pub fn end(&mut self) { + pub(crate) fn end(&mut self) { self.index = self.source.len(); } - pub fn start(&mut self) { + pub(crate) fn start(&mut self) { self.index = 0; } - pub fn position(&self) -> usize { + pub(crate) fn position(&self) -> usize { self.index } } diff --git a/crates/turtle/src/command/client/search/duration.rs b/crates/turtle/src/command/client/search/duration.rs index 54856c87..bc8dbed3 100644 --- a/crates/turtle/src/command/client/search/duration.rs +++ b/crates/turtle/src/command/client/search/duration.rs @@ -2,7 +2,7 @@ use core::fmt; use std::{ops::ControlFlow, time::Duration}; #[expect(clippy::module_name_repetitions)] -pub fn format_duration_into(dur: Duration, f: &mut fmt::Formatter<'_>) -> fmt::Result { +pub(crate) fn format_duration_into(dur: Duration, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn item(unit: &'static str, value: u64) -> ControlFlow<(&'static str, u64)> { if value > 0 { ControlFlow::Break((unit, value)) @@ -54,7 +54,7 @@ pub fn format_duration_into(dur: Duration, f: &mut fmt::Formatter<'_>) -> fmt::R } #[expect(clippy::module_name_repetitions)] -pub fn format_duration(f: Duration) -> String { +pub(crate) fn format_duration(f: Duration) -> String { struct F(Duration); impl fmt::Display for F { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/crates/turtle/src/command/client/search/engines.rs b/crates/turtle/src/command/client/search/engines.rs index 0f92b4c7..d6335a38 100644 --- a/crates/turtle/src/command/client/search/engines.rs +++ b/crates/turtle/src/command/client/search/engines.rs @@ -9,12 +9,12 @@ use eyre::Result; use super::cursor::Cursor; #[cfg(feature = "daemon")] -pub mod daemon; -pub mod db; -pub mod skim; +pub(crate) mod daemon; +pub(crate) mod db; +pub(crate) mod skim; #[expect(unused)] // settings is only used if daemon feature is enabled -pub fn engine(search_mode: SearchMode, settings: &Settings) -> Box<dyn SearchEngine> { +pub(crate) fn engine(search_mode: SearchMode, settings: &Settings) -> Box<dyn SearchEngine> { match search_mode { SearchMode::Skim => Box::new(skim::Search::new()) as Box<_>, #[cfg(feature = "daemon")] @@ -28,11 +28,11 @@ pub fn engine(search_mode: SearchMode, settings: &Settings) -> Box<dyn SearchEng } } -pub struct SearchState { - pub input: Cursor, - pub filter_mode: FilterMode, - pub context: Context, - pub custom_context: Option<HistoryId>, +pub(crate) struct SearchState { + pub(crate) input: Cursor, + pub(crate) filter_mode: FilterMode, + pub(crate) context: Context, + pub(crate) custom_context: Option<HistoryId>, } impl SearchState { @@ -63,7 +63,7 @@ impl SearchState { } #[async_trait] -pub trait SearchEngine: Send + Sync + 'static { +pub(crate) trait SearchEngine: Send + Sync + 'static { async fn full_query( &mut self, state: &SearchState, diff --git a/crates/turtle/src/command/client/search/engines/daemon.rs b/crates/turtle/src/command/client/search/engines/daemon.rs index b1299c02..df5ab9f8 100644 --- a/crates/turtle/src/command/client/search/engines/daemon.rs +++ b/crates/turtle/src/command/client/search/engines/daemon.rs @@ -16,7 +16,7 @@ use uuid::Uuid; use super::{SearchEngine, SearchState}; use crate::command::client::daemon; -pub struct Search { +pub(crate) struct Search { client: Option<SearchClient>, query_id: u64, settings: Settings, @@ -25,7 +25,7 @@ pub struct Search { } impl Search { - pub fn new(settings: &Settings) -> Self { + pub(crate) fn new(settings: &Settings) -> Self { Search { client: None, query_id: 0, diff --git a/crates/turtle/src/command/client/search/engines/db.rs b/crates/turtle/src/command/client/search/engines/db.rs index 2765faf5..86917a02 100644 --- a/crates/turtle/src/command/client/search/engines/db.rs +++ b/crates/turtle/src/command/client/search/engines/db.rs @@ -13,7 +13,7 @@ use norm::fzf::{FzfParser, FzfV2}; use std::ops::Range; use tracing::{Level, instrument}; -pub struct Search(pub SearchMode); +pub(crate) struct Search(pub(crate) SearchMode); #[async_trait] impl SearchEngine for Search { @@ -60,7 +60,7 @@ impl SearchEngine for Search { } #[instrument(skip_all, level = Level::TRACE, name = "db_highlight_fulltext")] -pub fn get_highlight_indices_fulltext(command: &str, search_input: &str) -> Vec<usize> { +pub(crate) fn get_highlight_indices_fulltext(command: &str, search_input: &str) -> Vec<usize> { let mut ranges = vec![]; let lower_command = command.to_ascii_lowercase(); diff --git a/crates/turtle/src/command/client/search/engines/skim.rs b/crates/turtle/src/command/client/search/engines/skim.rs index 96a6574d..fe2bdea3 100644 --- a/crates/turtle/src/command/client/search/engines/skim.rs +++ b/crates/turtle/src/command/client/search/engines/skim.rs @@ -16,13 +16,13 @@ use uuid; use super::{SearchEngine, SearchState}; -pub struct Search { +pub(crate) struct Search { all_history: Vec<(History, i32)>, engine: SkimMatcherV2, } impl Search { - pub fn new() -> Self { + pub(crate) fn new() -> Self { Search { all_history: vec![], engine: SkimMatcherV2::default(), diff --git a/crates/turtle/src/command/client/search/history_list.rs b/crates/turtle/src/command/client/search/history_list.rs index 4c83d7eb..9d3a60e0 100644 --- a/crates/turtle/src/command/client/search/history_list.rs +++ b/crates/turtle/src/command/client/search/history_list.rs @@ -19,19 +19,19 @@ use ratatui::{ }; use time::OffsetDateTime; -pub struct HistoryHighlighter<'a> { - pub engine: &'a dyn SearchEngine, - pub search_input: &'a str, +pub(crate) struct HistoryHighlighter<'a> { + pub(crate) engine: &'a dyn SearchEngine, + pub(crate) search_input: &'a str, } impl HistoryHighlighter<'_> { - pub fn get_highlight_indices(&self, command: &str) -> Vec<usize> { + pub(crate) fn get_highlight_indices(&self, command: &str) -> Vec<usize> { self.engine .get_highlight_indices(command, self.search_input) } } -pub struct HistoryList<'a> { +pub(crate) struct HistoryList<'a> { history: &'a [History], block: Option<Block<'a>>, inverted: bool, @@ -47,26 +47,26 @@ pub struct HistoryList<'a> { } #[derive(Default)] -pub struct ListState { +pub(crate) struct ListState { offset: usize, selected: usize, max_entries: usize, } impl ListState { - pub fn selected(&self) -> usize { + pub(crate) fn selected(&self) -> usize { self.selected } - pub fn max_entries(&self) -> usize { + pub(crate) fn max_entries(&self) -> usize { self.max_entries } - pub fn offset(&self) -> usize { + pub(crate) fn offset(&self) -> usize { self.offset } - pub fn select(&mut self, index: usize) { + pub(crate) fn select(&mut self, index: usize) { self.selected = index; } } @@ -118,7 +118,7 @@ impl StatefulWidget for HistoryList<'_> { impl<'a> HistoryList<'a> { #[expect(clippy::too_many_arguments)] - pub fn new( + pub(crate) fn new( history: &'a [History], inverted: bool, alternate_highlight: bool, @@ -143,7 +143,7 @@ impl<'a> HistoryList<'a> { } } - pub fn block(mut self, block: Block<'a>) -> Self { + pub(crate) fn block(mut self, block: Block<'a>) -> Self { self.block = Some(block); self } diff --git a/crates/turtle/src/command/client/search/inspector.rs b/crates/turtle/src/command/client/search/inspector.rs index 1ebc4383..a1bf803f 100644 --- a/crates/turtle/src/command/client/search/inspector.rs +++ b/crates/turtle/src/command/client/search/inspector.rs @@ -25,7 +25,7 @@ fn u64_or_zero(num: i64) -> u64 { if num < 0 { 0 } else { num as u64 } } -pub fn draw_commands( +pub(crate) fn draw_commands( f: &mut Frame<'_>, parent: Rect, history: &History, @@ -113,7 +113,7 @@ pub fn draw_commands( f.render_widget(next, commands[2]); } -pub fn draw_stats_table( +pub(crate) fn draw_stats_table( f: &mut Frame<'_>, parent: Rect, history: &History, @@ -285,7 +285,7 @@ fn draw_stats_charts(f: &mut Frame<'_>, parent: Rect, stats: &HistoryStats, them f.render_widget(duration_over_time, layout[2]); } -pub fn draw( +pub(crate) fn draw( f: &mut Frame<'_>, chunk: Rect, history: &History, @@ -302,7 +302,7 @@ pub fn draw( } } -pub fn draw_ultracompact( +pub(crate) fn draw_ultracompact( f: &mut Frame<'_>, chunk: Rect, history: &History, @@ -312,7 +312,7 @@ pub fn draw_ultracompact( draw_commands(f, chunk, history, stats, true, theme); } -pub fn draw_full( +pub(crate) fn draw_full( f: &mut Frame<'_>, chunk: Rect, history: &History, diff --git a/crates/turtle/src/command/client/search/interactive.rs b/crates/turtle/src/command/client/search/interactive.rs index a3d2cb79..380fc33b 100644 --- a/crates/turtle/src/command/client/search/interactive.rs +++ b/crates/turtle/src/command/client/search/interactive.rs @@ -52,7 +52,7 @@ use ratatui::crossterm::event::{ const TAB_TITLES: [&str; 2] = ["Search", "Inspect"]; -pub enum InputAction { +pub(crate) enum InputAction { Accept(usize), AcceptInspecting, Copy(usize), @@ -66,33 +66,33 @@ pub enum InputAction { } #[derive(Clone)] -pub struct InspectingState { +pub(crate) struct InspectingState { current: Option<HistoryId>, next: Option<HistoryId>, previous: Option<HistoryId>, } impl InspectingState { - pub fn move_to_previous(&mut self) { + pub(crate) fn move_to_previous(&mut self) { let previous = self.previous.clone(); self.reset(); self.current = previous; } - pub fn move_to_next(&mut self) { + pub(crate) fn move_to_next(&mut self) { let next = self.next.clone(); self.reset(); self.current = next; } - pub fn reset(&mut self) { + pub(crate) fn reset(&mut self) { self.current = None; self.next = None; self.previous = None; } } -pub fn to_compactness(f: &Frame, settings: &Settings) -> Compactness { +pub(crate) fn to_compactness(f: &Frame, settings: &Settings) -> Compactness { if match settings.style { crate::atuin_client::settings::Style::Auto => f.area().height < 14, crate::atuin_client::settings::Style::Compact => true, @@ -110,7 +110,7 @@ pub fn to_compactness(f: &Frame, settings: &Settings) -> Compactness { #[expect(clippy::struct_field_names)] #[expect(clippy::struct_excessive_bools)] -pub struct State { +pub(crate) struct State { history_count: i64, results_state: ListState, switched_search_mode: bool, @@ -124,7 +124,7 @@ pub struct State { pending_vim_key: Option<char>, original_input_empty: bool, - pub inspecting_state: InspectingState, + pub(crate) inspecting_state: InspectingState, keymaps: KeymapSet, search: SearchState, @@ -133,7 +133,7 @@ pub struct State { } #[derive(Clone, Copy)] -pub enum Compactness { +pub(crate) enum Compactness { Ultracompact, Compact, Full, @@ -231,7 +231,7 @@ impl State { } } - pub fn initialize_keymap_cursor(&mut self, settings: &Settings) { + pub(crate) fn initialize_keymap_cursor(&mut self, settings: &Settings) { match self.keymap_mode { KeymapMode::Emacs => self.set_keymap_cursor(settings, "emacs"), KeymapMode::VimNormal => self.set_keymap_cursor(settings, "vim_normal"), @@ -240,7 +240,7 @@ impl State { } } - pub fn finalize_keymap_cursor(&mut self, settings: &Settings) { + pub(crate) fn finalize_keymap_cursor(&mut self, settings: &Settings) { match settings.keymap_mode_shell { KeymapMode::Emacs => self.set_keymap_cursor(settings, "emacs"), KeymapMode::VimNormal => self.set_keymap_cursor(settings, "vim_normal"), @@ -1433,7 +1433,7 @@ struct Stdout { } impl Stdout { - pub fn new(inline_mode: bool, no_mouse: bool) -> std::io::Result<Self> { + pub(crate) fn new(inline_mode: bool, no_mouse: bool) -> std::io::Result<Self> { terminal::enable_raw_mode()?; let mut writer = TerminalWriter::new()?; @@ -1547,7 +1547,7 @@ fn compute_popup_placement( clippy::too_many_lines, clippy::cognitive_complexity )] -pub async fn history( +pub(crate) async fn history( query: &[String], settings: &Settings, mut db: impl Database, diff --git a/crates/turtle/src/command/client/search/keybindings/actions.rs b/crates/turtle/src/command/client/search/keybindings/actions.rs index ff2ef7de..341b030c 100644 --- a/crates/turtle/src/command/client/search/keybindings/actions.rs +++ b/crates/turtle/src/command/client/search/keybindings/actions.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; /// All possible actions that can be triggered by a keybinding. #[derive(Debug, Clone, PartialEq, Eq)] -pub enum Action { +pub(crate) enum Action { // Cursor movement CursorLeft, CursorRight, @@ -77,7 +77,7 @@ pub enum Action { impl Action { /// Convert from a kebab-case string. - pub fn from_str(s: &str) -> Result<Self, String> { + pub(crate) fn from_str(s: &str) -> Result<Self, String> { // Handle accept-N and return-selection-N patterns if let Some(rest) = s.strip_prefix("accept-") && let Ok(n) = rest.parse::<u8>() @@ -156,7 +156,7 @@ impl Action { } /// Convert to a kebab-case string. - pub fn as_str(&self) -> String { + pub(crate) fn as_str(&self) -> String { match self { Action::CursorLeft => "cursor-left".to_string(), Action::CursorRight => "cursor-right".to_string(), diff --git a/crates/turtle/src/command/client/search/keybindings/conditions.rs b/crates/turtle/src/command/client/search/keybindings/conditions.rs index 055ae905..f870d9a0 100644 --- a/crates/turtle/src/command/client/search/keybindings/conditions.rs +++ b/crates/turtle/src/command/client/search/keybindings/conditions.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; /// Atomic (leaf) conditions that can be evaluated against state. #[derive(Debug, Clone, PartialEq, Eq)] -pub enum ConditionAtom { +pub(crate) enum ConditionAtom { CursorAtStart, CursorAtEnd, InputEmpty, @@ -28,7 +28,7 @@ pub enum ConditionAtom { /// - `"list-at-start || no-results"` (disjunction) /// - `"(cursor-at-start && !input-empty) || no-results"` (grouping) #[derive(Debug, Clone, PartialEq, Eq)] -pub enum ConditionExpr { +pub(crate) enum ConditionExpr { Atom(ConditionAtom), Not(Box<ConditionExpr>), And(Box<ConditionExpr>, Box<ConditionExpr>), @@ -37,21 +37,21 @@ pub enum ConditionExpr { /// Context needed to evaluate conditions. This is a pure snapshot of state — /// no references to mutable data. -pub struct EvalContext { +pub(crate) struct EvalContext { /// Current cursor position (unicode width units). - pub cursor_position: usize, + pub(crate) cursor_position: usize, /// Width of the input string in unicode width units. - pub input_width: usize, + pub(crate) input_width: usize, /// Byte length of the input string. - pub input_byte_len: usize, + pub(crate) input_byte_len: usize, /// Currently selected index in the results list. - pub selected_index: usize, + pub(crate) selected_index: usize, /// Total number of results. - pub results_len: usize, + pub(crate) results_len: usize, /// Whether the original input (query passed to the TUI) was empty. - pub original_input_empty: bool, + pub(crate) original_input_empty: bool, /// Whether we use a search context of a command from the history. - pub has_context: bool, + pub(crate) has_context: bool, } // --------------------------------------------------------------------------- @@ -60,7 +60,7 @@ pub struct EvalContext { impl ConditionAtom { /// Evaluate this atom against the given context. - pub fn evaluate(&self, ctx: &EvalContext) -> bool { + pub(crate) fn evaluate(&self, ctx: &EvalContext) -> bool { match self { ConditionAtom::CursorAtStart => ctx.cursor_position == 0, ConditionAtom::CursorAtEnd => ctx.cursor_position == ctx.input_width, @@ -77,7 +77,7 @@ impl ConditionAtom { } /// Parse from a kebab-case string. - pub fn from_str(s: &str) -> Result<Self, String> { + pub(crate) fn from_str(s: &str) -> Result<Self, String> { match s { "cursor-at-start" => Ok(ConditionAtom::CursorAtStart), "cursor-at-end" => Ok(ConditionAtom::CursorAtEnd), @@ -93,7 +93,7 @@ impl ConditionAtom { } /// Convert to a kebab-case string. - pub fn as_str(&self) -> &'static str { + pub(crate) fn as_str(&self) -> &'static str { match self { ConditionAtom::CursorAtStart => "cursor-at-start", ConditionAtom::CursorAtEnd => "cursor-at-end", @@ -120,7 +120,7 @@ impl fmt::Display for ConditionAtom { impl ConditionExpr { /// Evaluate this expression against the given context. - pub fn evaluate(&self, ctx: &EvalContext) -> bool { + pub(crate) fn evaluate(&self, ctx: &EvalContext) -> bool { match self { ConditionExpr::Atom(atom) => atom.evaluate(ctx), ConditionExpr::Not(inner) => !inner.evaluate(ctx), @@ -143,17 +143,17 @@ impl From<ConditionAtom> for ConditionExpr { #[expect(dead_code)] impl ConditionExpr { /// Negate this expression: `!self`. - pub fn not(self) -> Self { + pub(crate) fn not(self) -> Self { ConditionExpr::Not(Box::new(self)) } /// Conjoin with another expression: `self && other`. - pub fn and(self, other: ConditionExpr) -> Self { + pub(crate) fn and(self, other: ConditionExpr) -> Self { ConditionExpr::And(Box::new(self), Box::new(other)) } /// Disjoin with another expression: `self || other`. - pub fn or(self, other: ConditionExpr) -> Self { + pub(crate) fn or(self, other: ConditionExpr) -> Self { ConditionExpr::Or(Box::new(self), Box::new(other)) } } @@ -286,7 +286,7 @@ impl<'a> ExprParser<'a> { impl ConditionExpr { /// Parse a condition expression from a string. - pub fn parse(s: &str) -> Result<Self, String> { + pub(crate) fn parse(s: &str) -> Result<Self, String> { let parser = ExprParser::new(s); parser.parse() } diff --git a/crates/turtle/src/command/client/search/keybindings/defaults.rs b/crates/turtle/src/command/client/search/keybindings/defaults.rs index c8401e37..6627c84d 100644 --- a/crates/turtle/src/command/client/search/keybindings/defaults.rs +++ b/crates/turtle/src/command/client/search/keybindings/defaults.rs @@ -49,12 +49,12 @@ fn key(s: &str) -> KeyInput { /// All five keymaps bundled together. #[derive(Debug, Clone)] -pub struct KeymapSet { - pub emacs: Keymap, - pub vim_normal: Keymap, - pub vim_insert: Keymap, - pub inspector: Keymap, - pub prefix: Keymap, +pub(crate) struct KeymapSet { + pub(crate) emacs: Keymap, + pub(crate) vim_normal: Keymap, + pub(crate) vim_insert: Keymap, + pub(crate) inspector: Keymap, + pub(crate) prefix: Keymap, } // --------------------------------------------------------------------------- @@ -101,7 +101,7 @@ fn accept_action(settings: &Settings) -> Action { /// - `ctrl_n_shortcuts` — whether alt or ctrl is used for numeric shortcuts // Keymap builder that enumerates every default binding; not worth splitting. #[expect(clippy::too_many_lines)] -pub fn default_emacs_keymap(settings: &Settings) -> Keymap { +pub(crate) fn default_emacs_keymap(settings: &Settings) -> Keymap { let mut km = Keymap::new(); add_common_bindings(&mut km); @@ -252,7 +252,7 @@ pub fn default_emacs_keymap(settings: &Settings) -> Keymap { // --------------------------------------------------------------------------- /// Build the default vim-normal keymap. -pub fn default_vim_normal_keymap(settings: &Settings) -> Keymap { +pub(crate) fn default_vim_normal_keymap(settings: &Settings) -> Keymap { let mut km = Keymap::new(); add_common_bindings(&mut km); @@ -333,7 +333,7 @@ pub fn default_vim_normal_keymap(settings: &Settings) -> Keymap { /// Build the default vim-insert keymap. This clones the emacs keymap and /// overlays vim-insert-specific bindings (esc → enter normal mode). -pub fn default_vim_insert_keymap(settings: &Settings) -> Keymap { +pub(crate) fn default_vim_insert_keymap(settings: &Settings) -> Keymap { let mut km = default_emacs_keymap(settings); // Override esc and ctrl-[ to enter normal mode instead of exiting @@ -353,7 +353,7 @@ pub fn default_vim_insert_keymap(settings: &Settings) -> Keymap { /// text input, so we build a minimal keymap with only inspector-relevant /// bindings. We respect the user's `keymap_mode` to provide vim-style j/k /// navigation for vim users. -pub fn default_inspector_keymap(settings: &Settings) -> Keymap { +pub(crate) fn default_inspector_keymap(settings: &Settings) -> Keymap { use crate::atuin_client::settings::KeymapMode; let mut km = Keymap::new(); @@ -400,7 +400,7 @@ pub fn default_inspector_keymap(settings: &Settings) -> Keymap { // --------------------------------------------------------------------------- /// Build the default prefix keymap (active after ctrl-a prefix). -pub fn default_prefix_keymap() -> Keymap { +pub(crate) fn default_prefix_keymap() -> Keymap { let mut km = Keymap::new(); km.bind(key("d"), Action::Delete); @@ -476,7 +476,7 @@ fn apply_config_to_keymap(keymap: &mut Keymap, overrides: &HashMap<String, KeyBi impl KeymapSet { /// Build the complete set of default keymaps from settings. - pub fn defaults(settings: &Settings) -> Self { + pub(crate) fn defaults(settings: &Settings) -> Self { KeymapSet { emacs: default_emacs_keymap(settings), vim_normal: default_vim_normal_keymap(settings), @@ -494,7 +494,7 @@ impl KeymapSet { /// overrides are applied per-key. /// - If `[keymap]` is empty/absent, `[keys]` customizes the defaults /// (current behavior for backward compatibility). - pub fn from_settings(settings: &Settings) -> Self { + pub(crate) fn from_settings(settings: &Settings) -> Self { use crate::atuin_client::settings::Keys; if settings.keymap.is_empty() { diff --git a/crates/turtle/src/command/client/search/keybindings/key.rs b/crates/turtle/src/command/client/search/keybindings/key.rs index c2eb31c6..35107a24 100644 --- a/crates/turtle/src/command/client/search/keybindings/key.rs +++ b/crates/turtle/src/command/client/search/keybindings/key.rs @@ -6,17 +6,17 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; /// A single key press with modifiers (e.g. `ctrl-c`, `alt-f`, `enter`). #[derive(Debug, Clone, PartialEq, Eq, Hash)] #[expect(clippy::struct_excessive_bools)] -pub struct SingleKey { - pub code: KeyCodeValue, - pub ctrl: bool, - pub alt: bool, - pub shift: bool, - pub super_key: bool, +pub(crate) struct SingleKey { + pub(crate) code: KeyCodeValue, + pub(crate) ctrl: bool, + pub(crate) alt: bool, + pub(crate) shift: bool, + pub(crate) super_key: bool, } /// The key code portion of a key press. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub enum KeyCodeValue { +pub(crate) enum KeyCodeValue { Char(char), Enter, Esc, @@ -39,14 +39,14 @@ pub enum KeyCodeValue { /// A key input that may be a single key or a multi-key sequence (e.g. `g g`). #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum KeyInput { +pub(crate) enum KeyInput { Single(SingleKey), Sequence(Vec<SingleKey>), } impl SingleKey { /// Convert a crossterm `KeyEvent` into a `SingleKey`. - pub fn from_event(event: &KeyEvent) -> Option<Self> { + pub(crate) fn from_event(event: &KeyEvent) -> Option<Self> { let ctrl = event.modifiers.contains(KeyModifiers::CONTROL); let alt = event.modifiers.contains(KeyModifiers::ALT); let shift = event.modifiers.contains(KeyModifiers::SHIFT); @@ -112,7 +112,7 @@ impl SingleKey { } /// Parse a key string like `"ctrl-c"`, `"alt-f"`, `"enter"`, `"G"`. - pub fn parse(s: &str) -> Result<Self, String> { + pub(crate) fn parse(s: &str) -> Result<Self, String> { let s = s.trim(); let parts: Vec<&str> = s.split('-').collect(); @@ -264,7 +264,7 @@ impl fmt::Display for SingleKey { impl KeyInput { /// Parse a key input string. Supports multi-key sequences separated by spaces /// (e.g. `"g g"`). - pub fn parse(s: &str) -> Result<Self, String> { + pub(crate) fn parse(s: &str) -> Result<Self, String> { let s = s.trim(); // Check for space-separated multi-key sequences // But don't split "space" or modifier combos like "ctrl-a" diff --git a/crates/turtle/src/command/client/search/keybindings/keymap.rs b/crates/turtle/src/command/client/search/keybindings/keymap.rs index 0d362863..c3b93b59 100644 --- a/crates/turtle/src/command/client/search/keybindings/keymap.rs +++ b/crates/turtle/src/command/client/search/keybindings/keymap.rs @@ -7,27 +7,27 @@ use super::key::{KeyInput, SingleKey}; /// A single rule within a keybinding: an optional condition and an action. /// If the condition is `None`, the rule always matches. #[derive(Debug, Clone)] -pub struct KeyRule { - pub condition: Option<ConditionExpr>, - pub action: Action, +pub(crate) struct KeyRule { + pub(crate) condition: Option<ConditionExpr>, + pub(crate) action: Action, } /// A keybinding is an ordered list of rules. The first rule whose condition /// matches (or has no condition) wins. #[derive(Debug, Clone)] -pub struct KeyBinding { - pub rules: Vec<KeyRule>, +pub(crate) struct KeyBinding { + pub(crate) rules: Vec<KeyRule>, } /// A keymap is a collection of keybindings indexed by key input. #[derive(Debug, Clone)] -pub struct Keymap { - pub bindings: HashMap<KeyInput, KeyBinding>, +pub(crate) struct Keymap { + pub(crate) bindings: HashMap<KeyInput, KeyBinding>, } impl KeyRule { /// Create an unconditional rule. - pub fn always(action: Action) -> Self { + pub(crate) fn always(action: Action) -> Self { KeyRule { condition: None, action, @@ -36,7 +36,7 @@ impl KeyRule { /// Create a conditional rule. Accepts any type convertible to `ConditionExpr`, /// including bare `ConditionAtom` values. - pub fn when(condition: impl Into<ConditionExpr>, action: Action) -> Self { + pub(crate) fn when(condition: impl Into<ConditionExpr>, action: Action) -> Self { KeyRule { condition: Some(condition.into()), action, @@ -46,39 +46,39 @@ impl KeyRule { impl KeyBinding { /// Create a simple (unconditional) binding. - pub fn simple(action: Action) -> Self { + pub(crate) fn simple(action: Action) -> Self { KeyBinding { rules: vec![KeyRule::always(action)], } } /// Create a conditional binding from a list of rules. - pub fn conditional(rules: Vec<KeyRule>) -> Self { + pub(crate) fn conditional(rules: Vec<KeyRule>) -> Self { KeyBinding { rules } } } impl Keymap { /// Create an empty keymap. - pub fn new() -> Self { + pub(crate) fn new() -> Self { Keymap { bindings: HashMap::new(), } } /// Bind a key input to a simple (unconditional) action. - pub fn bind(&mut self, key: KeyInput, action: Action) { + pub(crate) fn bind(&mut self, key: KeyInput, action: Action) { self.bindings.insert(key, KeyBinding::simple(action)); } /// Bind a key input to a conditional set of rules. - pub fn bind_conditional(&mut self, key: KeyInput, rules: Vec<KeyRule>) { + pub(crate) fn bind_conditional(&mut self, key: KeyInput, rules: Vec<KeyRule>) { self.bindings.insert(key, KeyBinding::conditional(rules)); } /// Resolve a key input to an action given the current evaluation context. /// Returns `None` if the key has no binding or no rule's condition matches. - pub fn resolve(&self, key: &KeyInput, ctx: &EvalContext) -> Option<Action> { + pub(crate) fn resolve(&self, key: &KeyInput, ctx: &EvalContext) -> Option<Action> { let binding = self.bindings.get(key)?; for rule in &binding.rules { match &rule.condition { @@ -92,7 +92,7 @@ impl Keymap { /// Check if any binding starts with the given single key as the first key /// of a multi-key sequence. Used to detect pending multi-key sequences. - pub fn has_sequence_starting_with(&self, prefix: &SingleKey) -> bool { + pub(crate) fn has_sequence_starting_with(&self, prefix: &SingleKey) -> bool { self.bindings.keys().any(|ki| match ki { KeyInput::Sequence(keys) => keys.first() == Some(prefix), KeyInput::Single(_) => false, @@ -101,7 +101,7 @@ impl Keymap { /// Merge another keymap into this one. Keys from `other` override keys in `self`. #[expect(dead_code)] - pub fn merge(&mut self, other: &Keymap) { + pub(crate) fn merge(&mut self, other: &Keymap) { for (key, binding) in &other.bindings { self.bindings.insert(key.clone(), binding.clone()); } diff --git a/crates/turtle/src/command/client/search/keybindings/mod.rs b/crates/turtle/src/command/client/search/keybindings/mod.rs index 3b6eb2b2..cdca0406 100644 --- a/crates/turtle/src/command/client/search/keybindings/mod.rs +++ b/crates/turtle/src/command/client/search/keybindings/mod.rs @@ -1,14 +1,14 @@ -pub mod actions; -pub mod conditions; -pub mod defaults; -pub mod key; -pub mod keymap; +pub(crate) mod actions; +pub(crate) mod conditions; +pub(crate) mod defaults; +pub(crate) mod key; +pub(crate) mod keymap; -pub use actions::Action; +pub(crate) use actions::Action; #[expect(unused_imports)] -pub use conditions::{ConditionAtom, ConditionExpr, EvalContext}; -pub use defaults::KeymapSet; +pub(crate) use conditions::{ConditionAtom, ConditionExpr, EvalContext}; +pub(crate) use defaults::KeymapSet; #[expect(unused_imports)] -pub use key::{KeyCodeValue, KeyInput, SingleKey}; +pub(crate) use key::{KeyCodeValue, KeyInput, SingleKey}; #[expect(unused_imports)] -pub use keymap::{KeyBinding, KeyRule, Keymap}; +pub(crate) use keymap::{KeyBinding, KeyRule, Keymap}; diff --git a/crates/turtle/src/command/client/server.rs b/crates/turtle/src/command/client/server.rs index 7de27551..4c2036d8 100644 --- a/crates/turtle/src/command/client/server.rs +++ b/crates/turtle/src/command/client/server.rs @@ -10,7 +10,7 @@ use eyre::{Context, Result, eyre}; #[derive(Subcommand, Clone, Debug)] #[command(infer_subcommands = true)] -pub enum Cmd { +pub(crate) enum Cmd { /// Start the server Start { /// The host address to bind @@ -28,7 +28,7 @@ pub enum Cmd { impl Cmd { #[expect(clippy::too_many_lines)] - pub async fn run(self) -> Result<()> { + pub(crate) async fn run(self) -> Result<()> { match self { Cmd::Start { host, port } => { let settings = Settings::new().wrap_err("could not load server settings")?; diff --git a/crates/turtle/src/command/client/setup.rs b/crates/turtle/src/command/client/setup.rs index b32ceb97..3231b6ec 100644 --- a/crates/turtle/src/command/client/setup.rs +++ b/crates/turtle/src/command/client/setup.rs @@ -5,7 +5,7 @@ use eyre::Result; use std::io::{self, Write}; use toml_edit::{DocumentMut, value}; -pub async fn run(_settings: &Settings) -> Result<()> { +pub(crate) async fn run(_settings: &Settings) -> Result<()> { let enable_ai = prompt( "Atuin AI", "This will enable command generation and other AI features via the question mark key", @@ -60,7 +60,7 @@ pub async fn run(_settings: &Settings) -> Result<()> { Ok(()) } -pub fn prompt(feature: &str, description: &str, note: Option<&str>) -> Result<bool> { +pub(crate) fn prompt(feature: &str, description: &str, note: Option<&str>) -> Result<bool> { println!( "> Enable {feature}?", feature = feature.bold().bright_blue() diff --git a/crates/turtle/src/command/client/stats.rs b/crates/turtle/src/command/client/stats.rs index fc10e949..98401cd3 100644 --- a/crates/turtle/src/command/client/stats.rs +++ b/crates/turtle/src/command/client/stats.rs @@ -25,7 +25,7 @@ fn parse_ngram_size(s: &str) -> Result<usize, String> { #[derive(Parser, Debug)] #[command(infer_subcommands = true)] -pub struct Cmd { +pub(crate) struct Cmd { /// Compute statistics for the specified period, leave blank for statistics since the beginning. See [this](https://docs.atuin.sh/reference/stats/) for more details. period: Vec<String>, @@ -39,7 +39,7 @@ pub struct Cmd { } impl Cmd { - pub async fn run(&self, db: &impl Database, settings: &Settings, theme: &Theme) -> Result<()> { + pub(crate) async fn run(&self, db: &impl Database, settings: &Settings, theme: &Theme) -> Result<()> { let context = current_context().await?; let words = if self.period.is_empty() { String::from("all") diff --git a/crates/turtle/src/command/client/store.rs b/crates/turtle/src/command/client/store.rs index dfa3b66c..3e9355b5 100644 --- a/crates/turtle/src/command/client/store.rs +++ b/crates/turtle/src/command/client/store.rs @@ -22,7 +22,7 @@ mod verify; #[derive(Subcommand, Debug)] #[command(infer_subcommands = true)] -pub enum Cmd { +pub(crate) enum Cmd { /// Print the current status of the record store Status, @@ -48,7 +48,7 @@ pub enum Cmd { } impl Cmd { - pub async fn run( + pub(crate) async fn run( &self, settings: &Settings, database: &dyn Database, @@ -69,7 +69,7 @@ impl Cmd { } } - pub async fn status(&self, store: SqliteStore) -> Result<()> { + pub(crate) async fn status(&self, store: SqliteStore) -> Result<()> { let host_id = Settings::host_id().await?; let offset = UtcOffset::current_local_offset().unwrap_or(UtcOffset::UTC); diff --git a/crates/turtle/src/command/client/store/pull.rs b/crates/turtle/src/command/client/store/pull.rs index c9c9c379..6b709a64 100644 --- a/crates/turtle/src/command/client/store/pull.rs +++ b/crates/turtle/src/command/client/store/pull.rs @@ -11,24 +11,24 @@ use crate::atuin_client::{ }; #[derive(Args, Debug)] -pub struct Pull { +pub(crate) struct Pull { /// The tag to push (eg, 'history'). Defaults to all tags #[arg(long, short)] - pub tag: Option<String>, + pub(crate) tag: Option<String>, /// Force push records /// This will first wipe the local store, and then download all records from the remote #[arg(long, default_value = "false")] - pub force: bool, + pub(crate) force: bool, /// Page Size /// How many records to download at once. Defaults to 100 #[arg(long, default_value = "100")] - pub page: u64, + pub(crate) page: u64, } impl Pull { - pub async fn run( + pub(crate) async fn run( &self, settings: &Settings, store: SqliteStore, diff --git a/crates/turtle/src/command/client/store/purge.rs b/crates/turtle/src/command/client/store/purge.rs index f7996c4b..3ed55787 100644 --- a/crates/turtle/src/command/client/store/purge.rs +++ b/crates/turtle/src/command/client/store/purge.rs @@ -8,10 +8,10 @@ use crate::atuin_client::{ }; #[derive(Args, Debug)] -pub struct Purge {} +pub(crate) struct Purge {} impl Purge { - pub async fn run(&self, settings: &Settings, store: SqliteStore) -> Result<()> { + pub(crate) async fn run(&self, settings: &Settings, store: SqliteStore) -> Result<()> { println!("Purging local records that cannot be decrypted"); let key = load_key(settings)?; diff --git a/crates/turtle/src/command/client/store/push.rs b/crates/turtle/src/command/client/store/push.rs index 724dfbef..042ad201 100644 --- a/crates/turtle/src/command/client/store/push.rs +++ b/crates/turtle/src/command/client/store/push.rs @@ -12,29 +12,29 @@ use crate::atuin_client::{ }; #[derive(Args, Debug)] -pub struct Push { +pub(crate) struct Push { /// The tag to push (eg, 'history'). Defaults to all tags #[arg(long, short)] - pub tag: Option<String>, + pub(crate) tag: Option<String>, /// The host to push, in the form of a UUID host ID. Defaults to the current host. #[arg(long)] - pub host: Option<Uuid>, + pub(crate) host: Option<Uuid>, /// Force push records /// This will override both host and tag, to be all hosts and all tags. First clear the remote store, then upload all of the /// local store #[arg(long, default_value = "false")] - pub force: bool, + pub(crate) force: bool, /// Page Size /// How many records to upload at once. Defaults to 100 #[arg(long, default_value = "100")] - pub page: u64, + pub(crate) page: u64, } impl Push { - pub async fn run(&self, settings: &Settings, store: SqliteStore) -> Result<()> { + pub(crate) async fn run(&self, settings: &Settings, store: SqliteStore) -> Result<()> { let host_id = Settings::host_id().await?; if self.force { diff --git a/crates/turtle/src/command/client/store/rebuild.rs b/crates/turtle/src/command/client/store/rebuild.rs index 80e201c2..0959b74e 100644 --- a/crates/turtle/src/command/client/store/rebuild.rs +++ b/crates/turtle/src/command/client/store/rebuild.rs @@ -10,12 +10,12 @@ use crate::atuin_client::{ }; #[derive(Args, Debug)] -pub struct Rebuild { - pub tag: String, +pub(crate) struct Rebuild { + pub(crate) tag: String, } impl Rebuild { - pub async fn run( + pub(crate) async fn run( &self, settings: &Settings, store: SqliteStore, diff --git a/crates/turtle/src/command/client/store/rekey.rs b/crates/turtle/src/command/client/store/rekey.rs index e63be447..3472222f 100644 --- a/crates/turtle/src/command/client/store/rekey.rs +++ b/crates/turtle/src/command/client/store/rekey.rs @@ -10,13 +10,13 @@ use crate::atuin_client::{ }; #[derive(Args, Debug)] -pub struct Rekey { +pub(crate) struct Rekey { /// The new key to use for encryption. Omit for a randomly-generated key key: Option<String>, } impl Rekey { - pub async fn run(&self, settings: &Settings, store: SqliteStore) -> Result<()> { + pub(crate) async fn run(&self, settings: &Settings, store: SqliteStore) -> Result<()> { let key = if let Some(key) = self.key.clone() { println!("Re-encrypting store with specified key"); diff --git a/crates/turtle/src/command/client/store/verify.rs b/crates/turtle/src/command/client/store/verify.rs index 5aa1dc70..e91addcf 100644 --- a/crates/turtle/src/command/client/store/verify.rs +++ b/crates/turtle/src/command/client/store/verify.rs @@ -8,10 +8,10 @@ use crate::atuin_client::{ }; #[derive(Args, Debug)] -pub struct Verify {} +pub(crate) struct Verify {} impl Verify { - pub async fn run(&self, settings: &Settings, store: SqliteStore) -> Result<()> { + pub(crate) async fn run(&self, settings: &Settings, store: SqliteStore) -> Result<()> { println!("Verifying local store can be decrypted with the current key"); let key = load_key(settings)?; diff --git a/crates/turtle/src/command/client/sync.rs b/crates/turtle/src/command/client/sync.rs index a4839b5f..8d7cb50a 100644 --- a/crates/turtle/src/command/client/sync.rs +++ b/crates/turtle/src/command/client/sync.rs @@ -15,7 +15,7 @@ use crate::command::client::account; #[derive(Subcommand, Debug)] #[command(infer_subcommands = true)] -pub enum Cmd { +pub(crate) enum Cmd { /// Sync with the configured server Sync { /// Force re-download everything @@ -40,7 +40,7 @@ pub enum Cmd { } impl Cmd { - pub async fn run( + pub(crate) async fn run( self, settings: Settings, db: &impl Database, diff --git a/crates/turtle/src/command/client/sync/status.rs b/crates/turtle/src/command/client/sync/status.rs index 00088b59..cb0d86e4 100644 --- a/crates/turtle/src/command/client/sync/status.rs +++ b/crates/turtle/src/command/client/sync/status.rs @@ -3,7 +3,7 @@ use crate::atuin_client::{api_client, settings::Settings}; use colored::Colorize; use eyre::{Result, bail}; -pub async fn run(settings: &Settings) -> Result<()> { +pub(crate) async fn run(settings: &Settings) -> Result<()> { if !settings.logged_in().await? { bail!("You are not logged in to a sync server - cannot show sync status"); } diff --git a/crates/turtle/src/command/client/wrapped.rs b/crates/turtle/src/command/client/wrapped.rs index 694157c2..5e41657e 100644 --- a/crates/turtle/src/command/client/wrapped.rs +++ b/crates/turtle/src/command/client/wrapped.rs @@ -163,7 +163,7 @@ impl WrappedStats { } } -pub fn print_wrapped_header(year: i32) { +pub(crate) fn print_wrapped_header(year: i32) { let reset = ResetColor; let bold = SetAttribute(crossterm::style::Attribute::Bold); @@ -266,7 +266,7 @@ fn print_fun_facts(wrapped_stats: &WrappedStats, stats: &Stats, year: i32) { println!(); } -pub async fn run( +pub(crate) async fn run( year: Option<i32>, db: &impl Database, settings: &Settings, diff --git a/crates/turtle/src/command/contributors.rs b/crates/turtle/src/command/contributors.rs index 452fd335..b2a41522 100644 --- a/crates/turtle/src/command/contributors.rs +++ b/crates/turtle/src/command/contributors.rs @@ -1,5 +1,5 @@ static CONTRIBUTORS: &str = include_str!("CONTRIBUTORS"); -pub fn run() { +pub(crate) fn run() { println!("\n{CONTRIBUTORS}"); } diff --git a/crates/turtle/src/command/external.rs b/crates/turtle/src/command/external.rs index e1f0cddd..a5daea21 100644 --- a/crates/turtle/src/command/external.rs +++ b/crates/turtle/src/command/external.rs @@ -10,7 +10,7 @@ use eyre::Result; use crate::Atuin; -pub fn run(args: &[String]) -> Result<()> { +pub(crate) fn run(args: &[String]) -> Result<()> { let subcommand = &args[0]; let bin = format!("atuin-{subcommand}"); let mut cmd = Command::new(&bin); diff --git a/crates/turtle/src/command/gen_completions.rs b/crates/turtle/src/command/gen_completions.rs index 10d4f689..7cc697d4 100644 --- a/crates/turtle/src/command/gen_completions.rs +++ b/crates/turtle/src/command/gen_completions.rs @@ -9,7 +9,7 @@ use eyre::Result; // into one command. #[derive(Debug, Clone, ValueEnum)] #[value(rename_all = "lower")] -pub enum GenShell { +pub(crate) enum GenShell { Bash, Elvish, Fish, @@ -49,7 +49,7 @@ impl Generator for GenShell { } #[derive(Debug, Parser)] -pub struct Cmd { +pub(crate) struct Cmd { /// Set the shell for generating completions #[arg(long, short)] shell: GenShell, @@ -60,7 +60,7 @@ pub struct Cmd { } impl Cmd { - pub fn run(self) -> Result<()> { + pub(crate) fn run(self) -> Result<()> { let Cmd { shell, out_dir } = self; let mut cli = crate::Atuin::command(); diff --git a/crates/turtle/src/command/mod.rs b/crates/turtle/src/command/mod.rs index e58bfe72..5d5d839e 100644 --- a/crates/turtle/src/command/mod.rs +++ b/crates/turtle/src/command/mod.rs @@ -16,7 +16,7 @@ mod external; #[derive(Subcommand)] #[command(infer_subcommands = true)] #[expect(clippy::large_enum_variant)] -pub enum AtuinCmd { +pub(crate) enum AtuinCmd { #[cfg(feature = "client")] #[command(flatten)] Client(client::Cmd), @@ -39,7 +39,7 @@ pub enum AtuinCmd { } impl AtuinCmd { - pub fn run(self) -> Result<()> { + pub(crate) fn run(self) -> Result<()> { #[cfg(not(windows))] { // set umask before we potentially open/create files diff --git a/crates/turtle/src/print_error.rs b/crates/turtle/src/print_error.rs index 4d4724bc..0a6303dd 100644 --- a/crates/turtle/src/print_error.rs +++ b/crates/turtle/src/print_error.rs @@ -7,7 +7,7 @@ use crossterm::terminal; /// Print a prominent error to stderr. Colored and box-bordered when stderr is /// a TTY, plain "Error: ..." header otherwise. The description is word-wrapped /// to the terminal width (capped at 100 columns) so the message stays readable. -pub fn print_error(title: &str, description: &str) { +pub(crate) fn print_error(title: &str, description: &str) { let is_tty = std::io::stderr().is_terminal(); let width = if is_tty { terminal::size().map_or(80, |(w, _)| w as usize) @@ -36,7 +36,7 @@ pub fn print_error(title: &str, description: &str) { /// Convert a `SyncError` into an `eyre::Report`, exiting on `WrongKey` after /// painting the prominent banner. -pub fn format_sync_error(e: SyncError) -> eyre::Report { +pub(crate) fn format_sync_error(e: SyncError) -> eyre::Report { if matches!(e, SyncError::WrongKey) { print_error( "Wrong encryption key", diff --git a/crates/turtle/src/sync.rs b/crates/turtle/src/sync.rs index 56aef615..cb743097 100644 --- a/crates/turtle/src/sync.rs +++ b/crates/turtle/src/sync.rs @@ -12,7 +12,7 @@ use crate::atuin_common::record::RecordId; /// Rebuild all stores after a sync /// Note: for history, this only does an _incremental_ sync. Hence the need to specify downloaded /// records. -pub async fn build( +pub(crate) async fn build( settings: &Settings, store: &SqliteStore, db: &dyn Database, |
