refactor(cli): compress build_*_item with prompt_or_flag
Plan B Phase 3 sub-step 2. Replaces the
title.map(Ok).unwrap_or_else(|| prompt("Title"))? chain in all
seven build_*_item functions with prompt_or_flag, and folds
login's or_else(|| prompt_optional(...).ok().flatten()) for
username and url into prompt_or_flag_optional. prompt_secret
sites and the parse-on-Some-only patterns (expiry, dob, card
kind, totp algorithm) stay as-is per spec. Removes the
#[allow(dead_code)] attributes from the four helpers in
prompt.rs now that callers exist.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -11,7 +11,7 @@ use anyhow::{Context, Result};
|
|||||||
|
|
||||||
use crate::AddKind;
|
use crate::AddKind;
|
||||||
use crate::parse::{base32_decode_lenient, guess_mime, parse_month_year};
|
use crate::parse::{base32_decode_lenient, guess_mime, parse_month_year};
|
||||||
use crate::prompt::{prompt, prompt_optional, prompt_secret};
|
use crate::prompt::{prompt, prompt_optional, prompt_or_flag, prompt_or_flag_optional, prompt_secret};
|
||||||
|
|
||||||
pub fn cmd_add(kind: AddKind) -> Result<()> {
|
pub fn cmd_add(kind: AddKind) -> Result<()> {
|
||||||
let vault = crate::session::UnlockedVault::unlock_interactive()?;
|
let vault = crate::session::UnlockedVault::unlock_interactive()?;
|
||||||
@@ -69,9 +69,9 @@ fn build_login_item(
|
|||||||
use relicario_core::{Item, ItemCore};
|
use relicario_core::{Item, ItemCore};
|
||||||
use zeroize::Zeroizing;
|
use zeroize::Zeroizing;
|
||||||
|
|
||||||
let title = title.map(Ok).unwrap_or_else(|| prompt("Title"))?;
|
let title = prompt_or_flag(title, "Title", |s| Ok(s.to_string()))?;
|
||||||
let username = username.or_else(|| prompt_optional("Username").ok().flatten());
|
let username = prompt_or_flag_optional(username, "Username", |s| Ok(s.to_string()))?;
|
||||||
let url = url.or_else(|| prompt_optional("URL").ok().flatten());
|
let url = prompt_or_flag_optional(url, "URL", |s| Ok(s.to_string()))?;
|
||||||
let parsed_url = match url {
|
let parsed_url = match url {
|
||||||
Some(s) => Some(url::Url::parse(&s).with_context(|| format!("invalid URL: {s}"))?),
|
Some(s) => Some(url::Url::parse(&s).with_context(|| format!("invalid URL: {s}"))?),
|
||||||
None => None,
|
None => None,
|
||||||
@@ -115,7 +115,7 @@ fn build_secure_note_item(
|
|||||||
use relicario_core::{Item, ItemCore};
|
use relicario_core::{Item, ItemCore};
|
||||||
use zeroize::Zeroizing;
|
use zeroize::Zeroizing;
|
||||||
|
|
||||||
let title = title.map(Ok).unwrap_or_else(|| prompt("Title"))?;
|
let title = prompt_or_flag(title, "Title", |s| Ok(s.to_string()))?;
|
||||||
let body = if body_prompt {
|
let body = if body_prompt {
|
||||||
eprintln!("Enter note body; end with Ctrl-D on a blank line:");
|
eprintln!("Enter note body; end with Ctrl-D on a blank line:");
|
||||||
let mut s = String::new();
|
let mut s = String::new();
|
||||||
@@ -144,7 +144,7 @@ fn build_identity_item(
|
|||||||
use relicario_core::item_types::IdentityCore;
|
use relicario_core::item_types::IdentityCore;
|
||||||
use relicario_core::{Item, ItemCore};
|
use relicario_core::{Item, ItemCore};
|
||||||
|
|
||||||
let title = title.map(Ok).unwrap_or_else(|| prompt("Title"))?;
|
let title = prompt_or_flag(title, "Title", |s| Ok(s.to_string()))?;
|
||||||
let dob = match date_of_birth {
|
let dob = match date_of_birth {
|
||||||
Some(s) => Some(chrono::NaiveDate::parse_from_str(&s, "%Y-%m-%d")
|
Some(s) => Some(chrono::NaiveDate::parse_from_str(&s, "%Y-%m-%d")
|
||||||
.with_context(|| format!("invalid date {s} (expected YYYY-MM-DD)"))?),
|
.with_context(|| format!("invalid date {s} (expected YYYY-MM-DD)"))?),
|
||||||
@@ -170,7 +170,7 @@ fn build_card_item(
|
|||||||
use relicario_core::{Item, ItemCore};
|
use relicario_core::{Item, ItemCore};
|
||||||
use zeroize::Zeroizing;
|
use zeroize::Zeroizing;
|
||||||
|
|
||||||
let title = title.map(Ok).unwrap_or_else(|| prompt("Title"))?;
|
let title = prompt_or_flag(title, "Title", |s| Ok(s.to_string()))?;
|
||||||
let number = Zeroizing::new(prompt_secret("Card number: ")?);
|
let number = Zeroizing::new(prompt_secret("Card number: ")?);
|
||||||
let cvv = Zeroizing::new(prompt_secret("CVV (blank to skip): ")?);
|
let cvv = Zeroizing::new(prompt_secret("CVV (blank to skip): ")?);
|
||||||
let cvv = if cvv.is_empty() { None } else { Some(cvv) };
|
let cvv = if cvv.is_empty() { None } else { Some(cvv) };
|
||||||
@@ -209,7 +209,7 @@ fn build_key_item(
|
|||||||
use relicario_core::{Item, ItemCore};
|
use relicario_core::{Item, ItemCore};
|
||||||
use zeroize::Zeroizing;
|
use zeroize::Zeroizing;
|
||||||
|
|
||||||
let title = title.map(Ok).unwrap_or_else(|| prompt("Title"))?;
|
let title = prompt_or_flag(title, "Title", |s| Ok(s.to_string()))?;
|
||||||
eprintln!("Paste key material; end with Ctrl-D on a blank line:");
|
eprintln!("Paste key material; end with Ctrl-D on a blank line:");
|
||||||
let mut key_material = String::new();
|
let mut key_material = String::new();
|
||||||
std::io::Read::read_to_string(&mut std::io::stdin(), &mut key_material)?;
|
std::io::Read::read_to_string(&mut std::io::stdin(), &mut key_material)?;
|
||||||
@@ -236,7 +236,7 @@ fn build_document_item(
|
|||||||
use relicario_core::{encrypt_attachment, AttachmentRef, Item, ItemCore};
|
use relicario_core::{encrypt_attachment, AttachmentRef, Item, ItemCore};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
let title = title.map(Ok).unwrap_or_else(|| prompt("Title"))?;
|
let title = prompt_or_flag(title, "Title", |s| Ok(s.to_string()))?;
|
||||||
let bytes = fs::read(&file)
|
let bytes = fs::read(&file)
|
||||||
.with_context(|| format!("failed to read {}", file.display()))?;
|
.with_context(|| format!("failed to read {}", file.display()))?;
|
||||||
let caps = vault.load_settings()?.attachment_caps;
|
let caps = vault.load_settings()?.attachment_caps;
|
||||||
@@ -285,7 +285,7 @@ fn build_totp_item(
|
|||||||
use relicario_core::{Item, ItemCore};
|
use relicario_core::{Item, ItemCore};
|
||||||
use zeroize::Zeroizing;
|
use zeroize::Zeroizing;
|
||||||
|
|
||||||
let title = title.map(Ok).unwrap_or_else(|| prompt("Title"))?;
|
let title = prompt_or_flag(title, "Title", |s| Ok(s.to_string()))?;
|
||||||
let secret_b32 = match secret {
|
let secret_b32 = match secret {
|
||||||
Some(s) => s,
|
Some(s) => s,
|
||||||
None => prompt_secret("TOTP secret (base32): ")?,
|
None => prompt_secret("TOTP secret (base32): ")?,
|
||||||
|
|||||||
@@ -80,8 +80,6 @@ pub(crate) fn prompt_yesno(label: &str) -> Result<bool> {
|
|||||||
Ok(matches!(s.trim().to_ascii_lowercase().as_str(), "y" | "yes"))
|
Ok(matches!(s.trim().to_ascii_lowercase().as_str(), "y" | "yes"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// dead_code allowed until sub-step 2 wires these into commands/add.rs.
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub(crate) fn prompt_or_flag<T>(
|
pub(crate) fn prompt_or_flag<T>(
|
||||||
flag: Option<T>,
|
flag: Option<T>,
|
||||||
label: &str,
|
label: &str,
|
||||||
@@ -92,7 +90,6 @@ pub(crate) fn prompt_or_flag<T>(
|
|||||||
prompt_or_flag_with_reader(flag, label, parser, &mut reader)
|
prompt_or_flag_with_reader(flag, label, parser, &mut reader)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub(crate) fn prompt_or_flag_optional<T>(
|
pub(crate) fn prompt_or_flag_optional<T>(
|
||||||
flag: Option<T>,
|
flag: Option<T>,
|
||||||
label: &str,
|
label: &str,
|
||||||
@@ -103,7 +100,6 @@ pub(crate) fn prompt_or_flag_optional<T>(
|
|||||||
prompt_or_flag_optional_with_reader(flag, label, parser, &mut reader)
|
prompt_or_flag_optional_with_reader(flag, label, parser, &mut reader)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub(crate) fn prompt_or_flag_with_reader<T, R: BufRead>(
|
pub(crate) fn prompt_or_flag_with_reader<T, R: BufRead>(
|
||||||
flag: Option<T>,
|
flag: Option<T>,
|
||||||
label: &str,
|
label: &str,
|
||||||
@@ -117,7 +113,6 @@ pub(crate) fn prompt_or_flag_with_reader<T, R: BufRead>(
|
|||||||
parser(&line)
|
parser(&line)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub(crate) fn prompt_or_flag_optional_with_reader<T, R: BufRead>(
|
pub(crate) fn prompt_or_flag_optional_with_reader<T, R: BufRead>(
|
||||||
flag: Option<T>,
|
flag: Option<T>,
|
||||||
label: &str,
|
label: &str,
|
||||||
|
|||||||
Reference in New Issue
Block a user