mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-13 05:28:49 +00:00
fish_indent: fix accidentally quadratic perf regression due to chars().last()
Iterator::last() consumes the entire iterator, even for DoubleEndedIterator, see https://github.com/rust-lang/rust/pull/28125#issuecomment-145070161 Because of this, "at_line_start()" took 90% of fish_indent share/completions/git.fish making it take 1000ms instead of 30 ms. Fix that.
This commit is contained in:
parent
57d7c46d22
commit
8d2fa4ae95
6 changed files with 7 additions and 7 deletions
|
@ -545,7 +545,7 @@ fn unescape_string_internal(input: &wstr, flags: UnescapeFlags) -> Option<WStrin
|
||||||
// In general, this is ANY_STRING. But as a hack, if the last appended char
|
// In general, this is ANY_STRING. But as a hack, if the last appended char
|
||||||
// is ANY_STRING, delete the last char and store ANY_STRING_RECURSIVE to
|
// is ANY_STRING, delete the last char and store ANY_STRING_RECURSIVE to
|
||||||
// reflect the fact that ** is the recursive wildcard.
|
// reflect the fact that ** is the recursive wildcard.
|
||||||
if result.chars().last() == Some(ANY_STRING) {
|
if result.chars().next_back() == Some(ANY_STRING) {
|
||||||
assert!(!result.is_empty());
|
assert!(!result.is_empty());
|
||||||
result.truncate(result.len() - 1);
|
result.truncate(result.len() - 1);
|
||||||
to_append_or_none = Some(ANY_STRING_RECURSIVE);
|
to_append_or_none = Some(ANY_STRING_RECURSIVE);
|
||||||
|
|
|
@ -319,7 +319,7 @@ impl<'source, 'ast> PrettyPrinterState<'source, 'ast> {
|
||||||
|
|
||||||
// \return whether we are at the start of a new line.
|
// \return whether we are at the start of a new line.
|
||||||
fn at_line_start(&self) -> bool {
|
fn at_line_start(&self) -> bool {
|
||||||
self.output.chars().last().is_none_or(|c| c == '\n')
|
self.output.chars().next_back().is_none_or(|c| c == '\n')
|
||||||
}
|
}
|
||||||
|
|
||||||
// \return whether we have a space before the output.
|
// \return whether we have a space before the output.
|
||||||
|
|
|
@ -782,7 +782,7 @@ pub fn is_potential_path(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
let mut abs_path = path_apply_working_directory(&clean_potential_path_fragment, wd);
|
let mut abs_path = path_apply_working_directory(&clean_potential_path_fragment, wd);
|
||||||
let must_be_full_dir = abs_path.chars().last() == Some('/');
|
let must_be_full_dir = abs_path.chars().next_back() == Some('/');
|
||||||
if flags.contains(PathFlags::PATH_FOR_CD) {
|
if flags.contains(PathFlags::PATH_FOR_CD) {
|
||||||
abs_path = normalize_path(&abs_path, /*allow_leading_double_slashes=*/ true);
|
abs_path = normalize_path(&abs_path, /*allow_leading_double_slashes=*/ true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -340,7 +340,7 @@ pub fn path_get_cdpath(dir: &wstr, wd: &wstr, vars: &dyn Environment) -> Option<
|
||||||
if dir.is_empty() {
|
if dir.is_empty() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
assert!(wd.chars().last() == Some('/'));
|
assert!(wd.chars().next_back() == Some('/'));
|
||||||
let paths = path_apply_cdpath(dir, wd, vars);
|
let paths = path_apply_cdpath(dir, wd, vars);
|
||||||
|
|
||||||
for a_dir in paths {
|
for a_dir in paths {
|
||||||
|
|
|
@ -3798,7 +3798,7 @@ fn get_autosuggestion_performer(
|
||||||
// Here we do something a little funny. If the line ends with a space, and the cursor is not
|
// Here we do something a little funny. If the line ends with a space, and the cursor is not
|
||||||
// at the end, don't use completion autosuggestions. It ends up being pretty weird seeing
|
// at the end, don't use completion autosuggestions. It ends up being pretty weird seeing
|
||||||
// stuff get spammed on the right while you go back to edit a line
|
// stuff get spammed on the right while you go back to edit a line
|
||||||
let last_char = search_string.chars().last().unwrap();
|
let last_char = search_string.chars().next_back().unwrap();
|
||||||
let cursor_at_end = cursor_pos == search_string.len();
|
let cursor_at_end = cursor_pos == search_string.len();
|
||||||
if !cursor_at_end && last_char.is_whitespace() {
|
if !cursor_at_end && last_char.is_whitespace() {
|
||||||
return nothing;
|
return nothing;
|
||||||
|
@ -4693,7 +4693,7 @@ impl ReaderData {
|
||||||
|
|
||||||
// Historical behavior is to trim trailing spaces, unless escape (#7661).
|
// Historical behavior is to trim trailing spaces, unless escape (#7661).
|
||||||
let mut text = self.command_line.text().to_owned();
|
let mut text = self.command_line.text().to_owned();
|
||||||
while text.chars().last() == Some(' ')
|
while text.chars().next_back() == Some(' ')
|
||||||
&& count_preceding_backslashes(&text, text.len() - 1) % 2 == 0
|
&& count_preceding_backslashes(&text, text.len() - 1) % 2 == 0
|
||||||
{
|
{
|
||||||
text.pop();
|
text.pop();
|
||||||
|
|
|
@ -632,7 +632,7 @@ mod expander {
|
||||||
// ANY_STRING_RECURSIVE character is present in both the head and the tail.
|
// ANY_STRING_RECURSIVE character is present in both the head and the tail.
|
||||||
let head_any = wc_segment.slice_to(asr_idx + 1);
|
let head_any = wc_segment.slice_to(asr_idx + 1);
|
||||||
let any_tail = wc.slice_from(asr_idx);
|
let any_tail = wc.slice_from(asr_idx);
|
||||||
assert!(head_any.chars().last().unwrap() == ANY_STRING_RECURSIVE);
|
assert!(head_any.chars().next_back().unwrap() == ANY_STRING_RECURSIVE);
|
||||||
assert!(any_tail.chars().next().unwrap() == ANY_STRING_RECURSIVE);
|
assert!(any_tail.chars().next().unwrap() == ANY_STRING_RECURSIVE);
|
||||||
|
|
||||||
dir.rewind();
|
dir.rewind();
|
||||||
|
|
Loading…
Reference in a new issue