mirror of
https://github.com/openai/codex.git
synced 2026-04-28 10:21:06 +03:00
5.1 KiB
5.1 KiB
DOs
- Normalize pasted paths robustly: Support
file://URLs, Windows drive/UNC paths, and single shell-escaped paths.
pub fn normalize_pasted_path(pasted: &str) -> Option<std::path::PathBuf> {
let pasted = pasted.trim();
if let Ok(url) = url::Url::parse(pasted)
&& url.scheme() == "file"
{
return url.to_file_path().ok();
}
let looks_like_windows = {
let drive = pasted.chars().next().map(|c| c.is_ascii_alphabetic()).unwrap_or(false)
&& pasted.get(1..2) == Some(":")
&& matches!(pasted.get(2..3), Some("\\") | Some("/"));
let unc = pasted.starts_with("\\\\");
drive || unc
};
if looks_like_windows {
return Some(pasted.into());
}
let parts: Vec<String> = shlex::Shlex::new(pasted).collect();
(parts.len() == 1).then(|| parts.into_iter().next().unwrap().into())
}
- Attach images from file paths and keep placeholders in submitted text: Validate dimensions, infer label, attach; do not strip placeholders on submit.
pub fn handle_paste_image_path(&mut self, pasted: String) -> bool {
let Some(path) = normalize_pasted_path(&pasted) else { return false; };
match image::image_dimensions(&path) {
Ok((w, h)) => {
let label = pasted_image_format(&path).label();
self.attach_image(path, w, h, label);
true
}
Err(_) => false,
}
}
// In paste handler:
if self.handle_paste_image_path(pasted.clone()) {
self.textarea.insert_str(" "); // keep placeholder in text
}
// In test:
match result {
InputResult::Submitted(text) => assert_eq!(text, "[image 10x5 PNG]"),
_ => panic!("expected Submitted"),
}
- Use a typed enum for image formats with a display label: Avoid stringly-typed formats.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum EncodedImageFormat { Png, Jpeg, Other }
impl EncodedImageFormat {
pub fn label(self) -> &'static str {
match self { Self::Png => "PNG", Self::Jpeg => "JPEG", Self::Other => "IMG" }
}
}
pub fn pasted_image_format(p: &std::path::Path) -> EncodedImageFormat {
match p.extension().and_then(|e| e.to_str()).map(|s| s.to_ascii_lowercase()).as_deref() {
Some("png") => EncodedImageFormat::Png,
Some("jpg") | Some("jpeg") => EncodedImageFormat::Jpeg,
_ => EncodedImageFormat::Other,
}
}
- Write clean, self-cleaning tests: Use
tempfile::tempdirand move imports to the top ofmod tests.
#[cfg(test)]
mod tests {
use super::*;
use image::{ImageBuffer, Rgba};
use tempfile::tempdir;
#[test]
fn pasting_filepath_attaches_image() {
let tmp = tempdir().expect("create TempDir");
let img_path = tmp.path().join("img.png");
ImageBuffer::<Rgba<u8>, _>::from_fn(3, 2, |_x, _y| Rgba([1,2,3,255]))
.save(&img_path)
.unwrap();
let needs_redraw = composer.handle_paste(img_path.to_string_lossy().to_string());
assert!(needs_redraw);
assert!(composer.textarea.text().starts_with("[image 3x2 PNG] "));
}
}
- Keep modules purpose-specific (avoid dumping grounds) and format consistently: Prefer descriptive module names and run formatters.
// Good: colocate path logic with clipboard handling or use specific modules
// file: tui/src/clipboard_paste.rs or tui/src/pasted_paths.rs
// Before committing:
$ just fmt
$ just fix -p codex-tui
- Declare necessary dependencies when introducing new APIs: Add
urlwhen usingurl::Url.
# codex-rs/tui/Cargo.toml
[dependencies]
url = "2"
DON’Ts
- Don’t create generic “utils.rs” dumping grounds: Use focused names like
clipboard_paste.rsorpasted_paths.rs.
// Avoid
// tui/src/string_utils.rs // collects unrelated helpers over time
// Prefer
// tui/src/pasted_paths.rs // narrowly focused on pasted path handling
- Don’t manually clean temp files in tests: Avoid
std::env::temp_dir()+ manualremove_file.
// Avoid
let path = std::env::temp_dir().join("leaky.png");
// ... write file ...
let _ = std::fs::remove_file(&path);
// Prefer
let tmp = tempfile::tempdir()?;
let path = tmp.path().join("scoped.png"); // auto-clean on drop
- Don’t strip image placeholders on submit: They should remain in the submitted text.
// Avoid
text = text.replace(&img.placeholder, ""); // removes "[image WxH ...]"
// Prefer
// leave placeholders intact; they represent attached content in text
- Don’t represent image formats as plain strings: Use a typed enum with a
label()for display.
// Avoid
let fmt = "png".to_string();
// Prefer
let fmt = pasted_image_format(path).label();
- Don’t parse Windows paths with POSIX-only assumptions: Detect drive/UNC forms and bypass POSIX escaping rules.
// Avoid
let parts: Vec<String> = shlex::Shlex::new(r"C:\Users\Me\img.png").collect(); // mis-parses
// Prefer
if looks_like_windows_path { return Some(PathBuf::from(pasted)); }
- Don’t skip formatting and linting: Ensure consistent style before landing.
just fmt
just fix -p codex-tui
cargo test -p codex-tui