use std::io::Read as _;
pub mod agent_surface;
pub mod apply;
pub mod backup;
pub mod batch;
pub mod calc;
pub mod case;
pub mod codemod;
pub mod copy;
pub mod count;
pub mod del;
pub mod delete;
pub mod diff;
pub mod edit;
pub mod edit_loop;
pub mod extract;
pub mod get;
pub mod hash;
pub mod list;
pub mod r#move;
#[cfg(feature = "ast")]
pub mod outline;
#[cfg(not(feature = "ast"))]
#[path = "outline_stub.rs"]
pub mod outline;
pub mod path_resolution;
pub mod prune_backups;
#[cfg(feature = "ast")]
pub mod query;
#[cfg(not(feature = "ast"))]
#[path = "query_stub.rs"]
pub mod query;
pub mod read;
pub mod recipe;
pub mod regex_gen;
pub mod replace;
pub mod rollback;
#[cfg(feature = "ast")]
pub mod scope;
#[cfg(not(feature = "ast"))]
#[path = "scope_stub.rs"]
pub mod scope;
pub mod search;
pub mod semantic_merge;
pub mod semantic_search;
pub mod set;
pub mod sparse;
#[cfg(feature = "ast")]
pub mod transform;
#[cfg(not(feature = "ast"))]
#[path = "transform_stub.rs"]
pub mod transform;
pub mod wal_stats;
pub mod watch;
pub mod write;
#[derive(Debug, Clone, Copy)]
pub(crate) struct ResolvedBackup {
pub backup: bool,
pub keep: bool,
pub retention: u8,
}
pub(crate) fn resolve_backup(
opts: &crate::cli_args::BackupOpts,
defaults: &crate::config::DefaultsSection,
) -> ResolvedBackup {
let backup = if let Ok(val) = std::env::var("ATOMWRITE_BACKUP") {
val != "0"
} else if opts.no_backup {
false
} else if opts.backup == Some(true) {
true
} else {
defaults.backup
};
ResolvedBackup {
backup,
keep: opts.keep_backup,
retention: opts.retention.unwrap_or(defaults.retention),
}
}
pub(crate) fn read_stdin_text_guarded(
stdin: impl std::io::Read,
max_size: u64,
stdin_is_tty: bool,
mode: &str,
) -> Result<String, crate::error::AtomwriteError> {
if stdin_is_tty {
return Err(crate::error::AtomwriteError::InvalidInput {
reason: format!(
"--{mode} reads content from stdin but stdin is a terminal; \
pipe content (echo 'new text' | atomwrite edit ...) or use --new-file"
),
});
}
let mut buf = String::new();
stdin.take(max_size).read_to_string(&mut buf)?;
Ok(buf)
}
#[cfg(test)]
mod tty_guard_tests {
use super::read_stdin_text_guarded;
use crate::error::AtomwriteError;
#[test]
fn tty_stdin_rejected_with_invalid_input() {
let result = read_stdin_text_guarded(std::io::empty(), 1024, true, "after-match");
match result {
Err(AtomwriteError::InvalidInput { reason }) => {
assert!(reason.contains("after-match"));
assert!(reason.contains("terminal"));
}
other => panic!("esperava InvalidInput, obteve {other:?}"),
}
}
#[test]
fn non_tty_stdin_reads_content() {
let content = read_stdin_text_guarded("hello\n".as_bytes(), 1024, false, "range")
.expect("deve ler stdin quando nao e tty");
assert_eq!(content, "hello\n");
}
#[test]
fn non_tty_stdin_respects_max_size() {
let content = read_stdin_text_guarded("abcdef".as_bytes(), 3, false, "between")
.expect("deve ler ate max_size");
assert_eq!(content, "abc");
}
}