@@ -118,6 +118,7 @@ pub fn file_picker(root: PathBuf, config: &helix_view::editor::Config) -> FilePi
118 .hidden(config.file_picker.hidden)
118 .hidden(config.file_picker.hidden)
119 .parents(config.file_picker.parents)
119 .parents(config.file_picker.parents)
120 .ignore(config.file_picker.ignore)
120 .ignore(config.file_picker.ignore)
121+ .follow_links(config.file_picker.follow_symlinks)
121 .git_ignore(config.file_picker.git_ignore)
122 .git_ignore(config.file_picker.git_ignore)
122 .git_global(config.file_picker.git_global)
123 .git_global(config.file_picker.git_global)
123 .git_exclude(config.file_picker.git_exclude)
124 .git_exclude(config.file_picker.git_exclude)
@@ -146,14 +147,13 @@ pub fn file_picker(root: PathBuf, config: &helix_view::editor::Config) -> FilePi
146 let entry = entry.ok()?;
147 let entry = entry.ok()?;
148 // This is faster than entry.path().is_dir() since it uses cached fs::Metadata fetched by ignore/walkdir
149 // This is faster than entry.path().is_dir() since it uses cached fs::Metadata fetched by ignore/walkdir
149− let is_dir = entry.file_type().map(|ft| ft.is_dir()).unwrap_or(false);
150+ let is_dir = entry.file_type().map_or(false, |ft| ft.is_dir());
151 if is_dir {
151 if is_dir {
152 // Will give a false positive if metadata cannot be read (eg. permission error)
152 // Will give a false positive if metadata cannot be read (eg. permission error)
153− return None;
153+ None
155+ Some(entry.into_path())
156− Some(entry.into_path())
159 // Cap the number of files if we aren't in a git project, preventing
159 // Cap the number of files if we aren't in a git project, preventing
@@ -175,9 +175,14 @@ pub fn file_picker(root: PathBuf, config: &helix_view::editor::Config) -> FilePi
175 path.strip_prefix(&root).unwrap_or(path).to_string_lossy()
175 path.strip_prefix(&root).unwrap_or(path).to_string_lossy()
177 move |cx, path: &PathBuf, action| {
177 move |cx, path: &PathBuf, action| {
179− .open(path.into(), action)
178+ if let Err(e) = cx.editor.open(path.into(), action) {
180− .expect("editor.open failed");
179+ let err = if let Some(err) = e.source() {
182+ format!("unable to open \"{}\"", path.display())
184+ cx.editor.set_error(err);
182 |_editor, path| Some((path.clone(), None)),
187 |_editor, path| Some((path.clone(), None)),
@@ -281,8 +286,8 @@ pub mod completers {
281 .collect()
286 .collect()
284− pub fn filename(_editor: &Editor, input: &str) -> Vec<Completion> {
289+ pub fn filename(editor: &Editor, input: &str) -> Vec<Completion> {
285− filename_impl(input, |entry| {
290+ filename_impl(editor, input, |entry| {
286 let is_dir = entry.file_type().map_or(false, |entry| entry.is_dir());
291 let is_dir = entry.file_type().map_or(false, |entry| entry.is_dir());
288 if is_dir {
293 if is_dir {
@@ -314,8 +319,8 @@ pub mod completers {
314 .collect()
319 .collect()
317− pub fn directory(_editor: &Editor, input: &str) -> Vec<Completion> {
322+ pub fn directory(editor: &Editor, input: &str) -> Vec<Completion> {
318− filename_impl(input, |entry| {
323+ filename_impl(editor, input, |entry| {
319 let is_dir = entry.file_type().map_or(false, |entry| entry.is_dir());
324 let is_dir = entry.file_type().map_or(false, |entry| entry.is_dir());
321 if is_dir {
326 if is_dir {
@@ -338,7 +343,7 @@ pub mod completers {
340 // TODO: we could return an iter/lazy thing so it can fetch as many as it needs.
345 // TODO: we could return an iter/lazy thing so it can fetch as many as it needs.
341− fn filename_impl<F>(input: &str, filter_fn: F) -> Vec<Completion>
346+ fn filename_impl<F>(editor: &Editor, input: &str, filter_fn: F) -> Vec<Completion>
343 F: Fn(&ignore::DirEntry) -> FileMatch,
348 F: Fn(&ignore::DirEntry) -> FileMatch,
@@ -370,6 +375,7 @@ pub mod completers {
371 let mut files: Vec<_> = WalkBuilder::new(&dir)
376 let mut files: Vec<_> = WalkBuilder::new(&dir)
372 .hidden(false)
377 .hidden(false)
378+ .follow_links(editor.config().file_picker.follow_symlinks)
373 .max_depth(Some(1))
379 .max_depth(Some(1))
375 .filter_map(|file| {
381 .filter_map(|file| {