From 8d44459c6ab1e1c7f26c8da4e6afafdb439c8450 Mon Sep 17 00:00:00 2001
From: Paul Olteanu <p.a.olteanu@gmail.com>
Date: Sat, 21 Oct 2023 05:20:29 -0400
Subject: [PATCH] Add helix-specific ignore files (#8099)

---
 helix-term/src/commands.rs | 141 +++++++++++++++++++------------------
 helix-term/src/ui/mod.rs   |   3 +
 2 files changed, 77 insertions(+), 67 deletions(-)

diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs
index 0fd011cc..75df430a 100644
--- a/helix-term/src/commands.rs
+++ b/helix-term/src/commands.rs
@@ -2184,7 +2184,10 @@ fn global_search(cx: &mut Context) {
                     let searcher = SearcherBuilder::new()
                         .binary_detection(BinaryDetection::quit(b'\x00'))
                         .build();
-                    WalkBuilder::new(search_root)
+
+                    let mut walk_builder = WalkBuilder::new(search_root);
+
+                    walk_builder
                         .hidden(file_picker_config.hidden)
                         .parents(file_picker_config.parents)
                         .ignore(file_picker_config.ignore)
@@ -2195,73 +2198,77 @@ fn global_search(cx: &mut Context) {
                         .max_depth(file_picker_config.max_depth)
                         .filter_entry(move |entry| {
                             filter_picker_entry(entry, &absolute_root, dedup_symlinks)
-                        })
-                        .build_parallel()
-                        .run(|| {
-                            let mut searcher = searcher.clone();
-                            let matcher = matcher.clone();
-                            let injector = injector_.clone();
-                            let documents = &documents;
-                            Box::new(move |entry: Result<DirEntry, ignore::Error>| -> WalkState {
-                                let entry = match entry {
-                                    Ok(entry) => entry,
-                                    Err(_) => return WalkState::Continue,
-                                };
-
-                                match entry.file_type() {
-                                    Some(entry) if entry.is_file() => {}
-                                    // skip everything else
-                                    _ => return WalkState::Continue,
-                                };
-
-                                let mut stop = false;
-                                let sink = sinks::UTF8(|line_num, _| {
-                                    stop = injector
-                                        .push(FileResult::new(entry.path(), line_num as usize - 1))
-                                        .is_err();
-
-                                    Ok(!stop)
-                                });
-                                let doc = documents.iter().find(|&(doc_path, _)| {
-                                    doc_path
-                                        .as_ref()
-                                        .map_or(false, |doc_path| doc_path == entry.path())
-                                });
-
-                                let result = if let Some((_, doc)) = doc {
-                                    // there is already a buffer for this file
-                                    // search the buffer instead of the file because it's faster
-                                    // and captures new edits without requiring a save
-                                    if searcher.multi_line_with_matcher(&matcher) {
-                                        // in this case a continous buffer is required
-                                        // convert the rope to a string
-                                        let text = doc.to_string();
-                                        searcher.search_slice(&matcher, text.as_bytes(), sink)
-                                    } else {
-                                        searcher.search_reader(
-                                            &matcher,
-                                            RopeReader::new(doc.slice(..)),
-                                            sink,
-                                        )
-                                    }
-                                } else {
-                                    searcher.search_path(&matcher, entry.path(), sink)
-                                };
-
-                                if let Err(err) = result {
-                                    log::error!(
-                                        "Global search error: {}, {}",
-                                        entry.path().display(),
-                                        err
-                                    );
-                                }
-                                if stop {
-                                    WalkState::Quit
-                                } else {
-                                    WalkState::Continue
-                                }
-                            })
                         });
+
+                    walk_builder
+                        .add_custom_ignore_filename(helix_loader::config_dir().join("ignore"));
+                    walk_builder.add_custom_ignore_filename(".helix/ignore");
+
+                    walk_builder.build_parallel().run(|| {
+                        let mut searcher = searcher.clone();
+                        let matcher = matcher.clone();
+                        let injector = injector_.clone();
+                        let documents = &documents;
+                        Box::new(move |entry: Result<DirEntry, ignore::Error>| -> WalkState {
+                            let entry = match entry {
+                                Ok(entry) => entry,
+                                Err(_) => return WalkState::Continue,
+                            };
+
+                            match entry.file_type() {
+                                Some(entry) if entry.is_file() => {}
+                                // skip everything else
+                                _ => return WalkState::Continue,
+                            };
+
+                            let mut stop = false;
+                            let sink = sinks::UTF8(|line_num, _| {
+                                stop = injector
+                                    .push(FileResult::new(entry.path(), line_num as usize - 1))
+                                    .is_err();
+
+                                Ok(!stop)
+                            });
+                            let doc = documents.iter().find(|&(doc_path, _)| {
+                                doc_path
+                                    .as_ref()
+                                    .map_or(false, |doc_path| doc_path == entry.path())
+                            });
+
+                            let result = if let Some((_, doc)) = doc {
+                                // there is already a buffer for this file
+                                // search the buffer instead of the file because it's faster
+                                // and captures new edits without requiring a save
+                                if searcher.multi_line_with_matcher(&matcher) {
+                                    // in this case a continous buffer is required
+                                    // convert the rope to a string
+                                    let text = doc.to_string();
+                                    searcher.search_slice(&matcher, text.as_bytes(), sink)
+                                } else {
+                                    searcher.search_reader(
+                                        &matcher,
+                                        RopeReader::new(doc.slice(..)),
+                                        sink,
+                                    )
+                                }
+                            } else {
+                                searcher.search_path(&matcher, entry.path(), sink)
+                            };
+
+                            if let Err(err) = result {
+                                log::error!(
+                                    "Global search error: {}, {}",
+                                    entry.path().display(),
+                                    err
+                                );
+                            }
+                            if stop {
+                                WalkState::Quit
+                            } else {
+                                WalkState::Continue
+                            }
+                        })
+                    });
                 });
 
                 cx.jobs.callback(async move {
diff --git a/helix-term/src/ui/mod.rs b/helix-term/src/ui/mod.rs
index 12ac1783..660bbfea 100644
--- a/helix-term/src/ui/mod.rs
+++ b/helix-term/src/ui/mod.rs
@@ -177,6 +177,9 @@ pub fn file_picker(root: PathBuf, config: &helix_view::editor::Config) -> Picker
         .max_depth(config.file_picker.max_depth)
         .filter_entry(move |entry| filter_picker_entry(entry, &absolute_root, dedup_symlinks));
 
+    walk_builder.add_custom_ignore_filename(helix_loader::config_dir().join("ignore"));
+    walk_builder.add_custom_ignore_filename(".helix/ignore");
+
     // We want to exclude files that the editor can't handle yet
     let mut type_builder = TypesBuilder::new();
     type_builder