chore: clippy on redundant closure (#4058)
Add redundant closure clippy rules and let Codex fix it by minimising FQP
This commit is contained in:
@@ -174,6 +174,8 @@ needless_option_as_deref = "deny"
|
|||||||
needless_question_mark = "deny"
|
needless_question_mark = "deny"
|
||||||
needless_update = "deny"
|
needless_update = "deny"
|
||||||
redundant_clone = "deny"
|
redundant_clone = "deny"
|
||||||
|
redundant_closure = "deny"
|
||||||
|
redundant_closure_for_method_calls = "deny"
|
||||||
redundant_static_lifetimes = "deny"
|
redundant_static_lifetimes = "deny"
|
||||||
trivially_copy_pass_by_ref = "deny"
|
trivially_copy_pass_by_ref = "deny"
|
||||||
uninlined_format_args = "deny"
|
uninlined_format_args = "deny"
|
||||||
|
|||||||
@@ -648,21 +648,18 @@ fn derive_new_contents_from_chunks(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut original_lines: Vec<String> = original_contents
|
let mut original_lines: Vec<String> = original_contents.split('\n').map(String::from).collect();
|
||||||
.split('\n')
|
|
||||||
.map(|s| s.to_string())
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
// Drop the trailing empty element that results from the final newline so
|
// Drop the trailing empty element that results from the final newline so
|
||||||
// that line counts match the behaviour of standard `diff`.
|
// that line counts match the behaviour of standard `diff`.
|
||||||
if original_lines.last().is_some_and(|s| s.is_empty()) {
|
if original_lines.last().is_some_and(String::is_empty) {
|
||||||
original_lines.pop();
|
original_lines.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
let replacements = compute_replacements(&original_lines, path, chunks)?;
|
let replacements = compute_replacements(&original_lines, path, chunks)?;
|
||||||
let new_lines = apply_replacements(original_lines, &replacements);
|
let new_lines = apply_replacements(original_lines, &replacements);
|
||||||
let mut new_lines = new_lines;
|
let mut new_lines = new_lines;
|
||||||
if !new_lines.last().is_some_and(|s| s.is_empty()) {
|
if !new_lines.last().is_some_and(String::is_empty) {
|
||||||
new_lines.push(String::new());
|
new_lines.push(String::new());
|
||||||
}
|
}
|
||||||
let new_contents = new_lines.join("\n");
|
let new_contents = new_lines.join("\n");
|
||||||
@@ -706,7 +703,7 @@ fn compute_replacements(
|
|||||||
if chunk.old_lines.is_empty() {
|
if chunk.old_lines.is_empty() {
|
||||||
// Pure addition (no old lines). We'll add them at the end or just
|
// Pure addition (no old lines). We'll add them at the end or just
|
||||||
// before the final empty line if one exists.
|
// before the final empty line if one exists.
|
||||||
let insertion_idx = if original_lines.last().is_some_and(|s| s.is_empty()) {
|
let insertion_idx = if original_lines.last().is_some_and(String::is_empty) {
|
||||||
original_lines.len() - 1
|
original_lines.len() - 1
|
||||||
} else {
|
} else {
|
||||||
original_lines.len()
|
original_lines.len()
|
||||||
@@ -732,11 +729,11 @@ fn compute_replacements(
|
|||||||
|
|
||||||
let mut new_slice: &[String] = &chunk.new_lines;
|
let mut new_slice: &[String] = &chunk.new_lines;
|
||||||
|
|
||||||
if found.is_none() && pattern.last().is_some_and(|s| s.is_empty()) {
|
if found.is_none() && pattern.last().is_some_and(String::is_empty) {
|
||||||
// Retry without the trailing empty line which represents the final
|
// Retry without the trailing empty line which represents the final
|
||||||
// newline in the file.
|
// newline in the file.
|
||||||
pattern = &pattern[..pattern.len() - 1];
|
pattern = &pattern[..pattern.len() - 1];
|
||||||
if new_slice.last().is_some_and(|s| s.is_empty()) {
|
if new_slice.last().is_some_and(String::is_empty) {
|
||||||
new_slice = &new_slice[..new_slice.len() - 1];
|
new_slice = &new_slice[..new_slice.len() - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -848,6 +845,7 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
use std::string::ToString;
|
||||||
use tempfile::tempdir;
|
use tempfile::tempdir;
|
||||||
|
|
||||||
/// Helper to construct a patch with the given body.
|
/// Helper to construct a patch with the given body.
|
||||||
@@ -856,7 +854,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn strs_to_strings(strs: &[&str]) -> Vec<String> {
|
fn strs_to_strings(strs: &[&str]) -> Vec<String> {
|
||||||
strs.iter().map(|s| s.to_string()).collect()
|
strs.iter().map(ToString::to_string).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test helpers to reduce repetition when building bash -lc heredoc scripts
|
// Test helpers to reduce repetition when building bash -lc heredoc scripts
|
||||||
|
|||||||
@@ -112,9 +112,10 @@ pub(crate) fn seek_sequence(
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::seek_sequence;
|
use super::seek_sequence;
|
||||||
|
use std::string::ToString;
|
||||||
|
|
||||||
fn to_vec(strings: &[&str]) -> Vec<String> {
|
fn to_vec(strings: &[&str]) -> Vec<String> {
|
||||||
strings.iter().map(|s| s.to_string()).collect()
|
strings.iter().map(ToString::to_string).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ where
|
|||||||
|
|
||||||
let argv1 = args.next().unwrap_or_default();
|
let argv1 = args.next().unwrap_or_default();
|
||||||
if argv1 == CODEX_APPLY_PATCH_ARG1 {
|
if argv1 == CODEX_APPLY_PATCH_ARG1 {
|
||||||
let patch_arg = args.next().and_then(|s| s.to_str().map(|s| s.to_owned()));
|
let patch_arg = args.next().and_then(|s| s.to_str().map(str::to_owned));
|
||||||
let exit_code = match patch_arg {
|
let exit_code = match patch_arg {
|
||||||
Some(patch_arg) => {
|
Some(patch_arg) => {
|
||||||
let mut stdout = std::io::stdout();
|
let mut stdout = std::io::stdout();
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use tree_sitter::Node;
|
||||||
use tree_sitter::Parser;
|
use tree_sitter::Parser;
|
||||||
use tree_sitter::Tree;
|
use tree_sitter::Tree;
|
||||||
use tree_sitter_bash::LANGUAGE as BASH;
|
use tree_sitter_bash::LANGUAGE as BASH;
|
||||||
@@ -74,7 +75,7 @@ pub fn try_parse_word_only_commands_sequence(tree: &Tree, src: &str) -> Option<V
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Walk uses a stack (LIFO), so re-sort by position to restore source order.
|
// Walk uses a stack (LIFO), so re-sort by position to restore source order.
|
||||||
command_nodes.sort_by_key(|node| node.start_byte());
|
command_nodes.sort_by_key(Node::start_byte);
|
||||||
|
|
||||||
let mut commands = Vec::new();
|
let mut commands = Vec::new();
|
||||||
for node in command_nodes {
|
for node in command_nodes {
|
||||||
|
|||||||
@@ -462,7 +462,7 @@ async fn process_chat_sse<S>(
|
|||||||
if let Some(reasoning_val) = choice.get("delta").and_then(|d| d.get("reasoning")) {
|
if let Some(reasoning_val) = choice.get("delta").and_then(|d| d.get("reasoning")) {
|
||||||
let mut maybe_text = reasoning_val
|
let mut maybe_text = reasoning_val
|
||||||
.as_str()
|
.as_str()
|
||||||
.map(|s| s.to_string())
|
.map(str::to_string)
|
||||||
.filter(|s| !s.is_empty());
|
.filter(|s| !s.is_empty());
|
||||||
|
|
||||||
if maybe_text.is_none() && reasoning_val.is_object() {
|
if maybe_text.is_none() && reasoning_val.is_object() {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use std::sync::OnceLock;
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::AuthManager;
|
use crate::AuthManager;
|
||||||
|
use crate::auth::CodexAuth;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use codex_protocol::mcp_protocol::AuthMode;
|
use codex_protocol::mcp_protocol::AuthMode;
|
||||||
use codex_protocol::mcp_protocol::ConversationId;
|
use codex_protocol::mcp_protocol::ConversationId;
|
||||||
@@ -337,7 +338,7 @@ impl ModelClient {
|
|||||||
// token.
|
// token.
|
||||||
let plan_type = error
|
let plan_type = error
|
||||||
.plan_type
|
.plan_type
|
||||||
.or_else(|| auth.as_ref().and_then(|a| a.get_plan_type()));
|
.or_else(|| auth.as_ref().and_then(CodexAuth::get_plan_type));
|
||||||
let resets_in_seconds = error.resets_in_seconds;
|
let resets_in_seconds = error.resets_in_seconds;
|
||||||
return Err(CodexErr::UsageLimitReached(UsageLimitReachedError {
|
return Err(CodexErr::UsageLimitReached(UsageLimitReachedError {
|
||||||
plan_type,
|
plan_type,
|
||||||
|
|||||||
@@ -1747,7 +1747,7 @@ async fn run_task(
|
|||||||
.unwrap_or(i64::MAX);
|
.unwrap_or(i64::MAX);
|
||||||
let total_usage_tokens = total_token_usage
|
let total_usage_tokens = total_token_usage
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|usage| usage.tokens_in_context_window());
|
.map(TokenUsage::tokens_in_context_window);
|
||||||
let token_limit_reached = total_usage_tokens
|
let token_limit_reached = total_usage_tokens
|
||||||
.map(|tokens| (tokens as i64) >= limit)
|
.map(|tokens| (tokens as i64) >= limit)
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ async fn persist_overrides_with_behavior(
|
|||||||
} else {
|
} else {
|
||||||
doc.get("profile")
|
doc.get("profile")
|
||||||
.and_then(|i| i.as_str())
|
.and_then(|i| i.as_str())
|
||||||
.map(|s| s.to_string())
|
.map(str::to_string)
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut mutated = false;
|
let mut mutated = false;
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ pub async fn discover_prompts_in_excluding(
|
|||||||
let Some(name) = path
|
let Some(name) = path
|
||||||
.file_stem()
|
.file_stem()
|
||||||
.and_then(|s| s.to_str())
|
.and_then(|s| s.to_str())
|
||||||
.map(|s| s.to_string())
|
.map(str::to_string)
|
||||||
else {
|
else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ async fn get_git_remotes(cwd: &Path) -> Option<Vec<String>> {
|
|||||||
let mut remotes: Vec<String> = String::from_utf8(output.stdout)
|
let mut remotes: Vec<String> = String::from_utf8(output.stdout)
|
||||||
.ok()?
|
.ok()?
|
||||||
.lines()
|
.lines()
|
||||||
.map(|s| s.to_string())
|
.map(str::to_string)
|
||||||
.collect();
|
.collect();
|
||||||
if let Some(pos) = remotes.iter().position(|r| r == "origin") {
|
if let Some(pos) = remotes.iter().position(|r| r == "origin") {
|
||||||
let origin = remotes.remove(pos);
|
let origin = remotes.remove(pos);
|
||||||
@@ -477,7 +477,7 @@ async fn diff_against_sha(cwd: &Path, sha: &GitSha) -> Option<String> {
|
|||||||
let untracked: Vec<String> = String::from_utf8(untracked_output.stdout)
|
let untracked: Vec<String> = String::from_utf8(untracked_output.stdout)
|
||||||
.ok()?
|
.ok()?
|
||||||
.lines()
|
.lines()
|
||||||
.map(|s| s.to_string())
|
.map(str::to_string)
|
||||||
.filter(|s| !s.is_empty())
|
.filter(|s| !s.is_empty())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
|||||||
@@ -160,9 +160,10 @@ fn is_valid_sed_n_arg(arg: Option<&str>) -> bool {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use std::string::ToString;
|
||||||
|
|
||||||
fn vec_str(args: &[&str]) -> Vec<String> {
|
fn vec_str(args: &[&str]) -> Vec<String> {
|
||||||
args.iter().map(|s| s.to_string()).collect()
|
args.iter().map(ToString::to_string).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -400,10 +400,7 @@ fn sanitize_json_schema(value: &mut JsonValue) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Normalize/ensure type
|
// Normalize/ensure type
|
||||||
let mut ty = map
|
let mut ty = map.get("type").and_then(|v| v.as_str()).map(str::to_string);
|
||||||
.get("type")
|
|
||||||
.and_then(|v| v.as_str())
|
|
||||||
.map(|s| s.to_string());
|
|
||||||
|
|
||||||
// If type is an array (union), pick first supported; else leave to inference
|
// If type is an array (union), pick first supported; else leave to inference
|
||||||
if ty.is_none()
|
if ty.is_none()
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ impl From<ParsedCommand> for codex_protocol::parse_command::ParsedCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn shlex_join(tokens: &[String]) -> String {
|
fn shlex_join(tokens: &[String]) -> String {
|
||||||
shlex_try_join(tokens.iter().map(|s| s.as_str()))
|
shlex_try_join(tokens.iter().map(String::as_str))
|
||||||
.unwrap_or_else(|_| "<command included NUL byte>".to_string())
|
.unwrap_or_else(|_| "<command included NUL byte>".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,13 +72,14 @@ pub fn parse_command(command: &[String]) -> Vec<ParsedCommand> {
|
|||||||
/// Tests are at the top to encourage using TDD + Codex to fix the implementation.
|
/// Tests are at the top to encourage using TDD + Codex to fix the implementation.
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use std::string::ToString;
|
||||||
|
|
||||||
fn shlex_split_safe(s: &str) -> Vec<String> {
|
fn shlex_split_safe(s: &str) -> Vec<String> {
|
||||||
shlex_split(s).unwrap_or_else(|| s.split_whitespace().map(|s| s.to_string()).collect())
|
shlex_split(s).unwrap_or_else(|| s.split_whitespace().map(ToString::to_string).collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn vec_str(args: &[&str]) -> Vec<String> {
|
fn vec_str(args: &[&str]) -> Vec<String> {
|
||||||
args.iter().map(|s| s.to_string()).collect()
|
args.iter().map(ToString::to_string).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assert_parsed(args: &[String], expected: Vec<ParsedCommand>) {
|
fn assert_parsed(args: &[String], expected: Vec<ParsedCommand>) {
|
||||||
@@ -894,7 +895,7 @@ fn simplify_once(commands: &[ParsedCommand]) -> Option<Vec<ParsedCommand>> {
|
|||||||
|
|
||||||
// echo ... && ...rest => ...rest
|
// echo ... && ...rest => ...rest
|
||||||
if let ParsedCommand::Unknown { cmd } = &commands[0]
|
if let ParsedCommand::Unknown { cmd } = &commands[0]
|
||||||
&& shlex_split(cmd).is_some_and(|t| t.first().map(|s| s.as_str()) == Some("echo"))
|
&& shlex_split(cmd).is_some_and(|t| t.first().map(String::as_str) == Some("echo"))
|
||||||
{
|
{
|
||||||
return Some(commands[1..].to_vec());
|
return Some(commands[1..].to_vec());
|
||||||
}
|
}
|
||||||
@@ -902,7 +903,7 @@ fn simplify_once(commands: &[ParsedCommand]) -> Option<Vec<ParsedCommand>> {
|
|||||||
// cd foo && [any command] => [any command] (keep non-cd when a cd is followed by something)
|
// cd foo && [any command] => [any command] (keep non-cd when a cd is followed by something)
|
||||||
if let Some(idx) = commands.iter().position(|pc| match pc {
|
if let Some(idx) = commands.iter().position(|pc| match pc {
|
||||||
ParsedCommand::Unknown { cmd } => {
|
ParsedCommand::Unknown { cmd } => {
|
||||||
shlex_split(cmd).is_some_and(|t| t.first().map(|s| s.as_str()) == Some("cd"))
|
shlex_split(cmd).is_some_and(|t| t.first().map(String::as_str) == Some("cd"))
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
}) && commands.len() > idx + 1
|
}) && commands.len() > idx + 1
|
||||||
@@ -1035,7 +1036,7 @@ fn short_display_path(path: &str) -> String {
|
|||||||
});
|
});
|
||||||
parts
|
parts
|
||||||
.next()
|
.next()
|
||||||
.map(|s| s.to_string())
|
.map(str::to_string)
|
||||||
.unwrap_or_else(|| trimmed.to_string())
|
.unwrap_or_else(|| trimmed.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1190,8 +1191,8 @@ fn parse_bash_lc_commands(original: &[String]) -> Option<Vec<ParsedCommand>> {
|
|||||||
if had_connectors {
|
if had_connectors {
|
||||||
let has_pipe = script_tokens.iter().any(|t| t == "|");
|
let has_pipe = script_tokens.iter().any(|t| t == "|");
|
||||||
let has_sed_n = script_tokens.windows(2).any(|w| {
|
let has_sed_n = script_tokens.windows(2).any(|w| {
|
||||||
w.first().map(|s| s.as_str()) == Some("sed")
|
w.first().map(String::as_str) == Some("sed")
|
||||||
&& w.get(1).map(|s| s.as_str()) == Some("-n")
|
&& w.get(1).map(String::as_str) == Some("-n")
|
||||||
});
|
});
|
||||||
if has_pipe && has_sed_n {
|
if has_pipe && has_sed_n {
|
||||||
ParsedCommand::Read {
|
ParsedCommand::Read {
|
||||||
@@ -1271,7 +1272,7 @@ fn is_small_formatting_command(tokens: &[String]) -> bool {
|
|||||||
// Keep `sed -n <range> file` (treated as a file read elsewhere);
|
// Keep `sed -n <range> file` (treated as a file read elsewhere);
|
||||||
// otherwise consider it a formatting helper in a pipeline.
|
// otherwise consider it a formatting helper in a pipeline.
|
||||||
tokens.len() < 4
|
tokens.len() < 4
|
||||||
|| !(tokens[1] == "-n" && is_valid_sed_n_arg(tokens.get(2).map(|s| s.as_str())))
|
|| !(tokens[1] == "-n" && is_valid_sed_n_arg(tokens.get(2).map(String::as_str)))
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
@@ -1318,7 +1319,7 @@ fn summarize_main_tokens(main_cmd: &[String]) -> ParsedCommand {
|
|||||||
(None, non_flags.first().map(|s| short_display_path(s)))
|
(None, non_flags.first().map(|s| short_display_path(s)))
|
||||||
} else {
|
} else {
|
||||||
(
|
(
|
||||||
non_flags.first().cloned().map(|s| s.to_string()),
|
non_flags.first().cloned().map(String::from),
|
||||||
non_flags.get(1).map(|s| short_display_path(s)),
|
non_flags.get(1).map(|s| short_display_path(s)),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
@@ -1353,7 +1354,7 @@ fn summarize_main_tokens(main_cmd: &[String]) -> ParsedCommand {
|
|||||||
.collect();
|
.collect();
|
||||||
// Do not shorten the query: grep patterns may legitimately contain slashes
|
// Do not shorten the query: grep patterns may legitimately contain slashes
|
||||||
// and should be preserved verbatim. Only paths should be shortened.
|
// and should be preserved verbatim. Only paths should be shortened.
|
||||||
let query = non_flags.first().cloned().map(|s| s.to_string());
|
let query = non_flags.first().cloned().map(String::from);
|
||||||
let path = non_flags.get(1).map(|s| short_display_path(s));
|
let path = non_flags.get(1).map(|s| short_display_path(s));
|
||||||
ParsedCommand::Search {
|
ParsedCommand::Search {
|
||||||
cmd: shlex_join(main_cmd),
|
cmd: shlex_join(main_cmd),
|
||||||
@@ -1363,7 +1364,7 @@ fn summarize_main_tokens(main_cmd: &[String]) -> ParsedCommand {
|
|||||||
}
|
}
|
||||||
Some((head, tail)) if head == "cat" => {
|
Some((head, tail)) if head == "cat" => {
|
||||||
// Support both `cat <file>` and `cat -- <file>` forms.
|
// Support both `cat <file>` and `cat -- <file>` forms.
|
||||||
let effective_tail: &[String] = if tail.first().map(|s| s.as_str()) == Some("--") {
|
let effective_tail: &[String] = if tail.first().map(String::as_str) == Some("--") {
|
||||||
&tail[1..]
|
&tail[1..]
|
||||||
} else {
|
} else {
|
||||||
tail
|
tail
|
||||||
@@ -1479,7 +1480,7 @@ fn summarize_main_tokens(main_cmd: &[String]) -> ParsedCommand {
|
|||||||
if head == "sed"
|
if head == "sed"
|
||||||
&& tail.len() >= 3
|
&& tail.len() >= 3
|
||||||
&& tail[0] == "-n"
|
&& tail[0] == "-n"
|
||||||
&& is_valid_sed_n_arg(tail.get(1).map(|s| s.as_str())) =>
|
&& is_valid_sed_n_arg(tail.get(1).map(String::as_str)) =>
|
||||||
{
|
{
|
||||||
if let Some(path) = tail.get(2) {
|
if let Some(path) = tail.get(2) {
|
||||||
let name = short_display_path(path);
|
let name = short_display_path(path);
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ impl Shell {
|
|||||||
return Some(command);
|
return Some(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
let joined = shlex::try_join(command.iter().map(|s| s.as_str())).ok();
|
let joined = shlex::try_join(command.iter().map(String::as_str)).ok();
|
||||||
return joined.map(|arg| {
|
return joined.map(|arg| {
|
||||||
vec![
|
vec![
|
||||||
ps.exe.clone(),
|
ps.exe.clone(),
|
||||||
@@ -111,7 +111,7 @@ fn format_shell_invocation_with_rc(
|
|||||||
rc_path: &str,
|
rc_path: &str,
|
||||||
) -> Option<Vec<String>> {
|
) -> Option<Vec<String>> {
|
||||||
let joined = strip_bash_lc(command)
|
let joined = strip_bash_lc(command)
|
||||||
.or_else(|| shlex::try_join(command.iter().map(|s| s.as_str())).ok())?;
|
.or_else(|| shlex::try_join(command.iter().map(String::as_str)).ok())?;
|
||||||
|
|
||||||
let rc_command = if std::path::Path::new(rc_path).exists() {
|
let rc_command = if std::path::Path::new(rc_path).exists() {
|
||||||
format!("source {rc_path} && ({joined})")
|
format!("source {rc_path} && ({joined})")
|
||||||
@@ -224,6 +224,7 @@ pub async fn default_user_shell() -> Shell {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
use std::string::ToString;
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_current_shell_detects_zsh() {
|
async fn test_current_shell_detects_zsh() {
|
||||||
@@ -327,7 +328,7 @@ mod tests {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let actual_cmd = shell
|
let actual_cmd = shell
|
||||||
.format_default_shell_invocation(input.iter().map(|s| s.to_string()).collect());
|
.format_default_shell_invocation(input.iter().map(ToString::to_string).collect());
|
||||||
let expected_cmd = expected_cmd
|
let expected_cmd = expected_cmd
|
||||||
.iter()
|
.iter()
|
||||||
.map(|s| s.replace("BASHRC_PATH", bashrc_path.to_str().unwrap()))
|
.map(|s| s.replace("BASHRC_PATH", bashrc_path.to_str().unwrap()))
|
||||||
@@ -371,6 +372,7 @@ mod tests {
|
|||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
mod macos_tests {
|
mod macos_tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use std::string::ToString;
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_run_with_profile_escaping_and_execution() {
|
async fn test_run_with_profile_escaping_and_execution() {
|
||||||
@@ -434,7 +436,7 @@ mod macos_tests {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let actual_cmd = shell
|
let actual_cmd = shell
|
||||||
.format_default_shell_invocation(input.iter().map(|s| s.to_string()).collect());
|
.format_default_shell_invocation(input.iter().map(ToString::to_string).collect());
|
||||||
let expected_cmd = expected_cmd
|
let expected_cmd = expected_cmd
|
||||||
.iter()
|
.iter()
|
||||||
.map(|s| s.replace("ZSHRC_PATH", zshrc_path.to_str().unwrap()))
|
.map(|s| s.replace("ZSHRC_PATH", zshrc_path.to_str().unwrap()))
|
||||||
@@ -559,10 +561,10 @@ mod tests_windows {
|
|||||||
|
|
||||||
for (shell, input, expected_cmd) in cases {
|
for (shell, input, expected_cmd) in cases {
|
||||||
let actual_cmd = shell
|
let actual_cmd = shell
|
||||||
.format_default_shell_invocation(input.iter().map(|s| s.to_string()).collect());
|
.format_default_shell_invocation(input.iter().map(|s| (*s).to_string()).collect());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
actual_cmd,
|
actual_cmd,
|
||||||
Some(expected_cmd.iter().map(|s| s.to_string()).collect())
|
Some(expected_cmd.iter().map(|s| (*s).to_string()).collect())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#![cfg(target_os = "macos")]
|
#![cfg(target_os = "macos")]
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::string::ToString;
|
||||||
|
|
||||||
use codex_core::exec::ExecParams;
|
use codex_core::exec::ExecParams;
|
||||||
use codex_core::exec::ExecToolCallOutput;
|
use codex_core::exec::ExecToolCallOutput;
|
||||||
@@ -29,7 +30,7 @@ async fn run_test_cmd(tmp: TempDir, cmd: Vec<&str>) -> Result<ExecToolCallOutput
|
|||||||
assert_eq!(sandbox_type, SandboxType::MacosSeatbelt);
|
assert_eq!(sandbox_type, SandboxType::MacosSeatbelt);
|
||||||
|
|
||||||
let params = ExecParams {
|
let params = ExecParams {
|
||||||
command: cmd.iter().map(|s| s.to_string()).collect(),
|
command: cmd.iter().map(ToString::to_string).collect(),
|
||||||
cwd: tmp.path().to_path_buf(),
|
cwd: tmp.path().to_path_buf(),
|
||||||
timeout_ms: Some(1000),
|
timeout_ms: Some(1000),
|
||||||
env: HashMap::new(),
|
env: HashMap::new(),
|
||||||
|
|||||||
@@ -573,7 +573,7 @@ impl EventProcessor for EventProcessorWithHumanOutput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn escape_command(command: &[String]) -> String {
|
fn escape_command(command: &[String]) -> String {
|
||||||
try_join(command.iter().map(|s| s.as_str())).unwrap_or_else(|_| command.join(" "))
|
try_join(command.iter().map(String::as_str)).unwrap_or_else(|_| command.join(" "))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format_file_change(change: &FileChange) -> &'static str {
|
fn format_file_change(change: &FileChange) -> &'static str {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ use anyhow::Context;
|
|||||||
use assert_cmd::prelude::*;
|
use assert_cmd::prelude::*;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
use std::string::ToString;
|
||||||
use tempfile::TempDir;
|
use tempfile::TempDir;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
use walkdir::WalkDir;
|
use walkdir::WalkDir;
|
||||||
@@ -45,7 +46,7 @@ fn find_session_file_containing_marker(
|
|||||||
&& payload.get("type").and_then(|t| t.as_str()) == Some("message")
|
&& payload.get("type").and_then(|t| t.as_str()) == Some("message")
|
||||||
&& payload
|
&& payload
|
||||||
.get("content")
|
.get("content")
|
||||||
.map(|c| c.to_string())
|
.map(ToString::to_string)
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
.contains(marker)
|
.contains(marker)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use std::borrow::Cow;
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@@ -108,7 +109,7 @@ fn ensure_absolute_path(path: &str, cwd: &Option<OsString>) -> Result<PathBuf> {
|
|||||||
file.absolutize()
|
file.absolutize()
|
||||||
};
|
};
|
||||||
result
|
result
|
||||||
.map(|path| path.into_owned())
|
.map(Cow::into_owned)
|
||||||
.map_err(|error| CannotCanonicalizePath {
|
.map_err(|error| CannotCanonicalizePath {
|
||||||
file: path.to_string(),
|
file: path.to_string(),
|
||||||
error: error.kind(),
|
error: error.kind(),
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ use codex_execpolicy::get_default_policy;
|
|||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde::de;
|
use serde::de;
|
||||||
|
use starlark::Error as StarlarkError;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
@@ -71,13 +72,13 @@ fn main() -> Result<()> {
|
|||||||
}
|
}
|
||||||
None => get_default_policy(),
|
None => get_default_policy(),
|
||||||
};
|
};
|
||||||
let policy = policy.map_err(|err| err.into_anyhow())?;
|
let policy = policy.map_err(StarlarkError::into_anyhow)?;
|
||||||
|
|
||||||
let exec = match args.command {
|
let exec = match args.command {
|
||||||
Command::Check { command } => match command.split_first() {
|
Command::Check { command } => match command.split_first() {
|
||||||
Some((first, rest)) => ExecArg {
|
Some((first, rest)) => ExecArg {
|
||||||
program: first.to_string(),
|
program: first.to_string(),
|
||||||
args: rest.iter().map(|s| s.to_string()).collect(),
|
args: rest.to_vec(),
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
eprintln!("no command provided");
|
eprintln!("no command provided");
|
||||||
@@ -161,6 +162,6 @@ impl FromStr for ExecArg {
|
|||||||
type Err = anyhow::Error;
|
type Err = anyhow::Error;
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
serde_json::from_str(s).map_err(|e| e.into())
|
serde_json::from_str(s).map_err(Into::into)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ impl ProgramSpec {
|
|||||||
let mut options = self
|
let mut options = self
|
||||||
.required_options
|
.required_options
|
||||||
.difference(&matched_opt_names)
|
.difference(&matched_opt_names)
|
||||||
.map(|s| s.to_string())
|
.map(String::from)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
options.sort();
|
options.sort();
|
||||||
return Err(Error::MissingRequiredOptions {
|
return Err(Error::MissingRequiredOptions {
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ async fn run_cmd(cmd: &[&str], writable_roots: &[PathBuf], timeout_ms: u64) {
|
|||||||
let cwd = std::env::current_dir().expect("cwd should exist");
|
let cwd = std::env::current_dir().expect("cwd should exist");
|
||||||
let sandbox_cwd = cwd.clone();
|
let sandbox_cwd = cwd.clone();
|
||||||
let params = ExecParams {
|
let params = ExecParams {
|
||||||
command: cmd.iter().map(|elm| elm.to_string()).collect(),
|
command: cmd.iter().copied().map(str::to_owned).collect(),
|
||||||
cwd,
|
cwd,
|
||||||
timeout_ms: Some(timeout_ms),
|
timeout_ms: Some(timeout_ms),
|
||||||
env: create_env_from_core_vars(),
|
env: create_env_from_core_vars(),
|
||||||
@@ -138,7 +138,7 @@ async fn assert_network_blocked(cmd: &[&str]) {
|
|||||||
let cwd = std::env::current_dir().expect("cwd should exist");
|
let cwd = std::env::current_dir().expect("cwd should exist");
|
||||||
let sandbox_cwd = cwd.clone();
|
let sandbox_cwd = cwd.clone();
|
||||||
let params = ExecParams {
|
let params = ExecParams {
|
||||||
command: cmd.iter().map(|s| s.to_string()).collect(),
|
command: cmd.iter().copied().map(str::to_owned).collect(),
|
||||||
cwd,
|
cwd,
|
||||||
// Give the tool a generous 2-second timeout so even slow DNS timeouts
|
// Give the tool a generous 2-second timeout so even slow DNS timeouts
|
||||||
// do not stall the suite.
|
// do not stall the suite.
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ use codex_core::default_client::ORIGINATOR;
|
|||||||
use codex_core::token_data::TokenData;
|
use codex_core::token_data::TokenData;
|
||||||
use codex_core::token_data::parse_id_token;
|
use codex_core::token_data::parse_id_token;
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
|
use serde_json::Value as JsonValue;
|
||||||
use tiny_http::Header;
|
use tiny_http::Header;
|
||||||
use tiny_http::Request;
|
use tiny_http::Request;
|
||||||
use tiny_http::Response;
|
use tiny_http::Response;
|
||||||
@@ -496,11 +497,11 @@ fn compose_success_url(port: u16, issuer: &str, id_token: &str, access_token: &s
|
|||||||
.unwrap_or("");
|
.unwrap_or("");
|
||||||
let completed_onboarding = token_claims
|
let completed_onboarding = token_claims
|
||||||
.get("completed_platform_onboarding")
|
.get("completed_platform_onboarding")
|
||||||
.and_then(|v| v.as_bool())
|
.and_then(JsonValue::as_bool)
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
let is_org_owner = token_claims
|
let is_org_owner = token_claims
|
||||||
.get("is_org_owner")
|
.get("is_org_owner")
|
||||||
.and_then(|v| v.as_bool())
|
.and_then(JsonValue::as_bool)
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
let needs_setup = (!completed_onboarding) && is_org_owner;
|
let needs_setup = (!completed_onboarding) && is_org_owner;
|
||||||
let plan_type = access_claims
|
let plan_type = access_claims
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ pub(crate) async fn handle_exec_approval_request(
|
|||||||
call_id: String,
|
call_id: String,
|
||||||
) {
|
) {
|
||||||
let escaped_command =
|
let escaped_command =
|
||||||
shlex::try_join(command.iter().map(|s| s.as_str())).unwrap_or_else(|_| command.join(" "));
|
shlex::try_join(command.iter().map(String::as_str)).unwrap_or_else(|_| command.join(" "));
|
||||||
let message = format!(
|
let message = format!(
|
||||||
"Allow Codex to run `{escaped_command}` in `{cwd}`?",
|
"Allow Codex to run `{escaped_command}` in `{cwd}`?",
|
||||||
cwd = cwd.to_string_lossy()
|
cwd = cwd.to_string_lossy()
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ fn create_expected_elicitation_request(
|
|||||||
) -> anyhow::Result<JSONRPCRequest> {
|
) -> anyhow::Result<JSONRPCRequest> {
|
||||||
let expected_message = format!(
|
let expected_message = format!(
|
||||||
"Allow Codex to run `{}` in `{}`?",
|
"Allow Codex to run `{}` in `{}`?",
|
||||||
shlex::try_join(command.iter().map(|s| s.as_ref()))?,
|
shlex::try_join(command.iter().map(std::convert::AsRef::as_ref))?,
|
||||||
workdir.to_string_lossy()
|
workdir.to_string_lossy()
|
||||||
);
|
);
|
||||||
Ok(JSONRPCRequest {
|
Ok(JSONRPCRequest {
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ impl OllamaClient {
|
|||||||
.map(|arr| {
|
.map(|arr| {
|
||||||
arr.iter()
|
arr.iter()
|
||||||
.filter_map(|v| v.get("name").and_then(|n| n.as_str()))
|
.filter_map(|v| v.get("name").and_then(|n| n.as_str()))
|
||||||
.map(|s| s.to_string())
|
.map(str::to_string)
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
})
|
})
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ pub(crate) fn pull_events_from_value(value: &JsonValue) -> Vec<PullEvent> {
|
|||||||
.and_then(|d| d.as_str())
|
.and_then(|d| d.as_str())
|
||||||
.unwrap_or("")
|
.unwrap_or("")
|
||||||
.to_string();
|
.to_string();
|
||||||
let total = value.get("total").and_then(|t| t.as_u64());
|
let total = value.get("total").and_then(JsonValue::as_u64);
|
||||||
let completed = value.get("completed").and_then(|t| t.as_u64());
|
let completed = value.get("completed").and_then(JsonValue::as_u64);
|
||||||
if total.is_some() || completed.is_some() {
|
if total.is_some() || completed.is_some() {
|
||||||
events.push(PullEvent::ChunkProgress {
|
events.push(PullEvent::ChunkProgress {
|
||||||
digest,
|
digest,
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ fn generate_index_ts(out_dir: &Path) -> Result<PathBuf> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut content =
|
let mut content =
|
||||||
String::with_capacity(HEADER.len() + entries.iter().map(|s| s.len()).sum::<usize>());
|
String::with_capacity(HEADER.len() + entries.iter().map(String::len).sum::<usize>());
|
||||||
content.push_str(HEADER);
|
content.push_str(HEADER);
|
||||||
for line in &entries {
|
for line in &entries {
|
||||||
content.push_str(line);
|
content.push_str(line);
|
||||||
|
|||||||
@@ -421,7 +421,7 @@ impl ChatComposer {
|
|||||||
// Capture any needed data from popup before clearing it.
|
// Capture any needed data from popup before clearing it.
|
||||||
let prompt_content = match sel {
|
let prompt_content = match sel {
|
||||||
CommandItem::UserPrompt(idx) => {
|
CommandItem::UserPrompt(idx) => {
|
||||||
popup.prompt_content(idx).map(|s| s.to_string())
|
popup.prompt_content(idx).map(str::to_string)
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
@@ -550,7 +550,7 @@ impl ChatComposer {
|
|||||||
let format_label = match Path::new(&sel_path)
|
let format_label = match Path::new(&sel_path)
|
||||||
.extension()
|
.extension()
|
||||||
.and_then(|e| e.to_str())
|
.and_then(|e| e.to_str())
|
||||||
.map(|s| s.to_ascii_lowercase())
|
.map(str::to_ascii_lowercase)
|
||||||
{
|
{
|
||||||
Some(ext) if ext == "png" => "PNG",
|
Some(ext) if ext == "png" => "PNG",
|
||||||
Some(ext) if ext == "jpg" || ext == "jpeg" => "JPEG",
|
Some(ext) if ext == "jpg" || ext == "jpeg" => "JPEG",
|
||||||
@@ -617,7 +617,7 @@ impl ChatComposer {
|
|||||||
text[safe_cursor..]
|
text[safe_cursor..]
|
||||||
.chars()
|
.chars()
|
||||||
.next()
|
.next()
|
||||||
.map(|c| c.is_whitespace())
|
.map(char::is_whitespace)
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
@@ -645,7 +645,7 @@ impl ChatComposer {
|
|||||||
let ws_len_right: usize = after_cursor
|
let ws_len_right: usize = after_cursor
|
||||||
.chars()
|
.chars()
|
||||||
.take_while(|c| c.is_whitespace())
|
.take_while(|c| c.is_whitespace())
|
||||||
.map(|c| c.len_utf8())
|
.map(char::len_utf8)
|
||||||
.sum();
|
.sum();
|
||||||
let start_right = safe_cursor + ws_len_right;
|
let start_right = safe_cursor + ws_len_right;
|
||||||
let end_right_rel = text[start_right..]
|
let end_right_rel = text[start_right..]
|
||||||
|
|||||||
@@ -218,6 +218,7 @@ impl WidgetRef for CommandPopup {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use std::string::ToString;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn filter_includes_init_when_typing_prefix() {
|
fn filter_includes_init_when_typing_prefix() {
|
||||||
@@ -287,7 +288,7 @@ mod tests {
|
|||||||
let mut prompt_names: Vec<String> = items
|
let mut prompt_names: Vec<String> = items
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|it| match it {
|
.filter_map(|it| match it {
|
||||||
CommandItem::UserPrompt(i) => popup.prompt_name(i).map(|s| s.to_string()),
|
CommandItem::UserPrompt(i) => popup.prompt_name(i).map(ToString::to_string),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ impl BottomPane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn active_view(&self) -> Option<&dyn BottomPaneView> {
|
fn active_view(&self) -> Option<&dyn BottomPaneView> {
|
||||||
self.view_stack.last().map(|view| view.as_ref())
|
self.view_stack.last().map(std::convert::AsRef::as_ref)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_view(&mut self, view: Box<dyn BottomPaneView>) {
|
fn push_view(&mut self, view: Box<dyn BottomPaneView>) {
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ impl PasteBurst {
|
|||||||
let start_byte = retro_start_index(before, retro_chars);
|
let start_byte = retro_start_index(before, retro_chars);
|
||||||
let grabbed = before[start_byte..].to_string();
|
let grabbed = before[start_byte..].to_string();
|
||||||
let looks_pastey =
|
let looks_pastey =
|
||||||
grabbed.chars().any(|c| c.is_whitespace()) || grabbed.chars().count() >= 16;
|
grabbed.chars().any(char::is_whitespace) || grabbed.chars().count() >= 16;
|
||||||
if looks_pastey {
|
if looks_pastey {
|
||||||
// Note: caller is responsible for removing this slice from UI text.
|
// Note: caller is responsible for removing this slice from UI text.
|
||||||
self.begin_with_retro_grabbed(grabbed.clone(), now);
|
self.begin_with_retro_grabbed(grabbed.clone(), now);
|
||||||
|
|||||||
@@ -616,7 +616,7 @@ impl ChatWidget {
|
|||||||
self.flush_answer_stream_with_separator();
|
self.flush_answer_stream_with_separator();
|
||||||
// Emit the proposed command into history (like proposed patches)
|
// Emit the proposed command into history (like proposed patches)
|
||||||
self.add_to_history(history_cell::new_proposed_command(&ev.command));
|
self.add_to_history(history_cell::new_proposed_command(&ev.command));
|
||||||
let command = shlex::try_join(ev.command.iter().map(|s| s.as_str()))
|
let command = shlex::try_join(ev.command.iter().map(String::as_str))
|
||||||
.unwrap_or_else(|_| ev.command.join(" "));
|
.unwrap_or_else(|_| ev.command.join(" "));
|
||||||
self.notify(Notification::ExecApprovalRequested { command });
|
self.notify(Notification::ExecApprovalRequested { command });
|
||||||
|
|
||||||
|
|||||||
@@ -1044,7 +1044,10 @@ async fn binary_size_transcript_snapshot() {
|
|||||||
call_id: e.call_id.clone(),
|
call_id: e.call_id.clone(),
|
||||||
command: e.command,
|
command: e.command,
|
||||||
cwd: e.cwd,
|
cwd: e.cwd,
|
||||||
parsed_cmd: parsed_cmd.into_iter().map(|c| c.into()).collect(),
|
parsed_cmd: parsed_cmd
|
||||||
|
.into_iter()
|
||||||
|
.map(std::convert::Into::into)
|
||||||
|
.collect(),
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1121,7 +1124,7 @@ async fn binary_size_transcript_snapshot() {
|
|||||||
// Trim trailing spaces to match plain text fixture
|
// Trim trailing spaces to match plain text fixture
|
||||||
lines.push(s.trim_end().to_string());
|
lines.push(s.trim_end().to_string());
|
||||||
}
|
}
|
||||||
while lines.last().is_some_and(|l| l.is_empty()) {
|
while lines.last().is_some_and(std::string::String::is_empty) {
|
||||||
lines.pop();
|
lines.pop();
|
||||||
}
|
}
|
||||||
// Consider content only after the last session banner marker. Skip the transient
|
// Consider content only after the last session banner marker. Skip the transient
|
||||||
|
|||||||
@@ -198,7 +198,7 @@ pub fn pasted_image_format(path: &Path) -> EncodedImageFormat {
|
|||||||
match path
|
match path
|
||||||
.extension()
|
.extension()
|
||||||
.and_then(|e| e.to_str())
|
.and_then(|e| e.to_str())
|
||||||
.map(|s| s.to_ascii_lowercase())
|
.map(str::to_ascii_lowercase)
|
||||||
.as_deref()
|
.as_deref()
|
||||||
{
|
{
|
||||||
Some("png") => EncodedImageFormat::Png,
|
Some("png") => EncodedImageFormat::Png,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use diffy::Hunk;
|
||||||
use ratatui::style::Color;
|
use ratatui::style::Color;
|
||||||
use ratatui::style::Modifier;
|
use ratatui::style::Modifier;
|
||||||
use ratatui::style::Style;
|
use ratatui::style::Style;
|
||||||
@@ -283,7 +284,7 @@ fn calculate_add_remove_from_diff(diff: &str) -> (usize, usize) {
|
|||||||
patch
|
patch
|
||||||
.hunks()
|
.hunks()
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|h| h.lines())
|
.flat_map(Hunk::lines)
|
||||||
.fold((0, 0), |(a, d), l| match l {
|
.fold((0, 0), |(a, d), l| match l {
|
||||||
diffy::Line::Insert(_) => (a + 1, d),
|
diffy::Line::Insert(_) => (a + 1, d),
|
||||||
diffy::Line::Delete(_) => (a, d + 1),
|
diffy::Line::Delete(_) => (a, d + 1),
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use dirs::home_dir;
|
|||||||
use shlex::try_join;
|
use shlex::try_join;
|
||||||
|
|
||||||
pub(crate) fn escape_command(command: &[String]) -> String {
|
pub(crate) fn escape_command(command: &[String]) -> String {
|
||||||
try_join(command.iter().map(|s| s.as_str())).unwrap_or_else(|_| command.join(" "))
|
try_join(command.iter().map(String::as_str)).unwrap_or_else(|_| command.join(" "))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn strip_bash_lc_and_escape(command: &[String]) -> String {
|
pub(crate) fn strip_bash_lc_and_escape(command: &[String]) -> String {
|
||||||
|
|||||||
@@ -388,7 +388,7 @@ impl ExecCell {
|
|||||||
vec![(
|
vec![(
|
||||||
"Read",
|
"Read",
|
||||||
itertools::Itertools::intersperse(
|
itertools::Itertools::intersperse(
|
||||||
names.into_iter().map(|n| n.into()),
|
names.into_iter().map(Into::into),
|
||||||
", ".dim(),
|
", ".dim(),
|
||||||
)
|
)
|
||||||
.collect(),
|
.collect(),
|
||||||
|
|||||||
@@ -50,11 +50,7 @@ pub(crate) fn render_markdown_text_with_citations(
|
|||||||
let mut options = Options::empty();
|
let mut options = Options::empty();
|
||||||
options.insert(Options::ENABLE_STRIKETHROUGH);
|
options.insert(Options::ENABLE_STRIKETHROUGH);
|
||||||
let parser = Parser::new_ext(input, options);
|
let parser = Parser::new_ext(input, options);
|
||||||
let mut w = Writer::new(
|
let mut w = Writer::new(parser, scheme.map(str::to_string), Some(cwd.to_path_buf()));
|
||||||
parser,
|
|
||||||
scheme.map(|s| s.to_string()),
|
|
||||||
Some(cwd.to_path_buf()),
|
|
||||||
);
|
|
||||||
w.run();
|
w.run();
|
||||||
w.text
|
w.text
|
||||||
}
|
}
|
||||||
@@ -329,7 +325,7 @@ where
|
|||||||
let is_ordered = self
|
let is_ordered = self
|
||||||
.list_indices
|
.list_indices
|
||||||
.last()
|
.last()
|
||||||
.map(|index| index.is_some())
|
.map(Option::is_some)
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
let width = depth * 4 - 3;
|
let width = depth * 4 - 3;
|
||||||
let marker = if let Some(last_index) = self.list_indices.last_mut() {
|
let marker = if let Some(last_index) = self.list_indices.last_mut() {
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ impl WidgetRef for &ModelUpgradePopup {
|
|||||||
let mut lines: Vec<Line> = Vec::new();
|
let mut lines: Vec<Line> = Vec::new();
|
||||||
if show_animation {
|
if show_animation {
|
||||||
let frame = self.animation.current_frame();
|
let frame = self.animation.current_frame();
|
||||||
lines.extend(frame.lines().map(|l| l.into()));
|
lines.extend(frame.lines().map(Into::into));
|
||||||
// Spacer between animation and text content.
|
// Spacer between animation and text content.
|
||||||
lines.push("".into());
|
lines.push("".into());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ impl WidgetRef for &WelcomeWidget {
|
|||||||
let frame = self.animation.current_frame();
|
let frame = self.animation.current_frame();
|
||||||
// let frame_line_count = frame.lines().count();
|
// let frame_line_count = frame.lines().count();
|
||||||
// lines.reserve(frame_line_count + 2);
|
// lines.reserve(frame_line_count + 2);
|
||||||
lines.extend(frame.lines().map(|l| l.into()));
|
lines.extend(frame.lines().map(Into::into));
|
||||||
lines.push("".into());
|
lines.push("".into());
|
||||||
}
|
}
|
||||||
lines.push(Line::from(vec![
|
lines.push(Line::from(vec![
|
||||||
|
|||||||
@@ -382,7 +382,7 @@ impl TranscriptOverlay {
|
|||||||
let cell_lines = if Some(idx) == highlight_cell {
|
let cell_lines = if Some(idx) == highlight_cell {
|
||||||
cell.transcript_lines()
|
cell.transcript_lines()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|l| l.reversed())
|
.map(Stylize::reversed)
|
||||||
.collect()
|
.collect()
|
||||||
} else {
|
} else {
|
||||||
cell.transcript_lines()
|
cell.transcript_lines()
|
||||||
|
|||||||
@@ -329,6 +329,7 @@ mod tests {
|
|||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
use ratatui::style::Color;
|
use ratatui::style::Color;
|
||||||
use ratatui::style::Stylize;
|
use ratatui::style::Stylize;
|
||||||
|
use std::string::ToString;
|
||||||
|
|
||||||
fn concat_line(line: &Line) -> String {
|
fn concat_line(line: &Line) -> String {
|
||||||
line.spans
|
line.spans
|
||||||
@@ -543,7 +544,7 @@ mod tests {
|
|||||||
let lines = [line];
|
let lines = [line];
|
||||||
// Force small width to exercise wrapping at spaces.
|
// Force small width to exercise wrapping at spaces.
|
||||||
let wrapped = word_wrap_lines_borrowed(&lines, 40);
|
let wrapped = word_wrap_lines_borrowed(&lines, 40);
|
||||||
let joined: String = wrapped.iter().map(|l| l.to_string()).join("\n");
|
let joined: String = wrapped.iter().map(ToString::to_string).join("\n");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
joined,
|
joined,
|
||||||
r#"Years passed, and Willowmere thrived
|
r#"Years passed, and Willowmere thrived
|
||||||
|
|||||||
Reference in New Issue
Block a user