Repository: helix-editor/helix
File: helix-term/src/ui/mod.rs (Rust)

Code before:
                                compositor.push(Box::new(overlay::overlaid(picker)));
                            }
                        }));
                    Ok(call)
                });
                cx.jobs.callback(callback);
            } else if let Err(e) = cx.editor.open(path, action) {
                let err = if let Some(err) = e.source() {
                    format!("{}", err)
                } else {
                    format!("unable to open \"{}\"", path.display())
                };
                cx.editor.set_error(err);
            }
        },
    )
    .with_preview(|_editor, path| Some((path.as_path().into(), None)));

    Ok(picker)
}

fn directory_content(path: &Path) -> Result<Vec<PathBuf>, std::io::Error> {
    let mut dirs = Vec::new();
    let mut files = Vec::new();
    for entry in std::fs::read_dir(path)?.flatten() {
        if entry.path().is_dir() {
            dirs.push(entry.path());
        } else {
            files.push(entry.path());
        }
    }
    dirs.sort();
    files.sort();

    let mut content = Vec::new();
    if path.parent().is_some() {
        content.insert(0, path.join(".."));
    }
    content.extend(dirs);
    content.extend(files);
    Ok(content)
}

pub mod completers {
    use crate::ui::prompt::Completion;
    use helix_core::fuzzy::fuzzy_match;
    use helix_core::syntax::LanguageServerFeature;
    use helix_view::document::SCRATCH_BUFFER_NAME;
    use helix_view::theme;
    use helix_view::{editor::Config, Editor};
    use once_cell::sync::Lazy;

Review comment (suggestion):
We should try to avoid `Path::is_dir` (and equivalents like `PathBuf::is_dir`) since they mean a syscall per call. We can avoid that here (most of the time, platform dependent) by using `DirEntry::file_type`:

```suggestion
        if entry.file_type().is_ok_and(|file_type| file_type.is_dir()) {
```

I would also switch the return Vec from this function to be `Vec<(PathBuf, bool)>`, so we keep that `is_dir` boolean around rather than calling `path.is_dir()` elsewhere (especially while rendering). This will make the file browser type different than FilePicker:

```rust
type FileBrowser = Picker<(PathBuf, bool), PathBuf>;
```

The type will diverge anyways in order to theme directories (see below...)

Code after:
            }
        },
    )];
    let picker = Picker::new(
        columns,
        0,
        directory_content,
        (root, directory_style),
        move |cx, (path, is_dir): &(PathBuf, bool), action| {
            if *is_dir {
                let new_root = helix_stdx::path::normalize(path);
                let callback = Box::pin(async move {
                    let call: Callback =
                        Callback::EditorCompositor(Box::new(move |editor, compositor| {
                            if let Ok(picker) = file_browser(new_root, editor) {
                                compositor.push(Box::new(overlay::overlaid(picker)));
                            }
                        }));
                    Ok(call)
                });
                cx.jobs.callback(callback);
            } else if let Err(e) = cx.editor.open(path, action) {
                let err = if let Some(err) = e.source() {
                    format!("{}", err)
                } else {
                    format!("unable to open \"{}\"", path.display())
                };
                cx.editor.set_error(err);
            }
        },
    )
    .with_preview(|_editor, (path, _is_dir)| Some((path.as_path().into(), None)));

    Ok(picker)
}

fn directory_content(path: &Path) -> Result<Vec<(PathBuf, bool)>, std::io::Error> {
    let mut content: Vec<_> = std::fs::read_dir(path)?
        .flatten()
        .map(|entry| {
            (
                entry.path(),
                entry.file_type().is_ok_and(|file_type| file_type.is_dir()),
            )
        })
        .collect();

    content.sort_by(|(path1, is_dir1), (path2, is_dir2)| (!is_dir1, path1).cmp(&(!is_dir2, path2)));
    if path.parent().is_some() {
        content.insert(0, (path.join(".."), true));
    }