diff --git a/pd/nw/dialog_search.html b/pd/nw/dialog_search.html
index 8f3640b5600932512ab32510553ce91736fdf1a0..74a7e95ef33e3008c762a833fe7c2e2a6f673fab 100644
--- a/pd/nw/dialog_search.html
+++ b/pd/nw/dialog_search.html
@@ -837,7 +837,19 @@ function display_doc(doc) {
     }
     if (doc.related_objects) {
         var p_rel_objs = document.createElement("p");
-        p_rel_objs.innerHTML = "Related objects: ".bold() + doc.related_objects.toString();
+        var ref_rel_objs = doc.ref_related_objects.split("\,");
+        p_rel_objs.innerHTML = "Related objects: ".bold();
+        doc.related_objects.split(" ").forEach(function (rel_obj, i, a) {
+            let link_rel_obj = rel_obj;
+            // for the objects with a help patch, add a link to its -help.pd
+            if (ref_rel_objs[i]) {
+                let ref_rel_obj = "javascript: pdgui.doc_open('" +
+                      pdgui.defunkify_windows_path(path.dirname(ref_rel_objs[i])) + "', '" +
+                      pdgui.defunkify_windows_path(path.basename(ref_rel_objs[i])) + "');";
+                link_rel_obj = rel_obj.link(ref_rel_obj);
+            }
+            p_rel_objs.innerHTML += " " + link_rel_obj;
+        });
         p_rel_objs.style.marginTop = "-10px";
         div.appendChild(p_rel_objs);
     }
diff --git a/pd/nw/pdgui.js b/pd/nw/pdgui.js
index c49f66e5cad4d596793217ff6cd39fe33ef623ed..e430f4ba85cb7246395f9e4d86d10be757270106 100644
--- a/pd/nw/pdgui.js
+++ b/pd/nw/pdgui.js
@@ -13,6 +13,14 @@ exports.get_pwd = function() {
     return pwd;
 }
 
+function funkify_windows_path(s) {
+    var ret = s;
+    if (process.platform === "win32") {
+        ret = ret.replace(/\//g, "\\");
+    }
+    return ret;
+}
+
 function defunkify_windows_path(s) {
     var ret = s;
     if (process.platform === "win32") {
@@ -25,6 +33,8 @@ exports.set_pd_engine_id = function (id) {
     pd_engine_id = id;
 }
 
+exports.funkify_windows_path = funkify_windows_path;
+
 exports.defunkify_windows_path = defunkify_windows_path;
 
 function gui_set_browser_config(doc_flag, path_flag, init_flag, helppath) {
@@ -112,8 +122,8 @@ function init_elasticlunr()
     index.addField("keywords");
     index.addField("description");
     index.addField("related_objects");
-    //index.addField("body");
-    index.addField("path");
+    index.addField("ref_related_objects");
+    index.addField("dir");
     index.setRef("id");
     return index;
 }
@@ -122,6 +132,12 @@ var index = init_elasticlunr();
 var index_cache = new Array();
 var index_manif = new Set();
 
+function regex_dir(dir) {
+    let str_regex = funkify_windows_path(dir).replace(/\\/g, "\\\\").replace(/\//g, "\\\/")
+        + "\\" + path.sep + "?([\\w]*)\\" + path.sep + "?([\\w|\\.|\\-|\\~]*)\\" + path.sep + "?([\\S]*)";
+    return (RegExp(str_regex.toString()));
+}
+
 function index_entry_esc(s) {
     if (s) {
         var t = s.replace(/\\/g, "\\\\").replace(/:/g, "\\:");
@@ -131,8 +147,15 @@ function index_entry_esc(s) {
     }
 }
 
-function add_doc_to_index(filename, data) {
-    var rel_objs;
+// GB: Add related_objects, keywords and description of files in indexing
+function add_doc_details_to_index(filename, data) {
+    var title = path.basename(filename, "-help.pd"),
+        big_line = data.replace("\n", " "),
+        keywords,
+        desc,
+        rel_objs,
+        ref_rel_objs;
+    // GB: investigate the related objects of each file
     const machine_related_objects = {
         found_objects: [],
         ref_found_objs: [],
@@ -147,38 +170,55 @@ function add_doc_to_index(filename, data) {
             },
             SEARCHING_OBJS: {
                 search_regex: function(line_search) {
-                    var rel_obj = line_search.match(/#X obj \-?\d+ \-?\d+ (pddp\/helplink )?(\w*\/)?([\w|\~]*);/i);
+                    var rel_obj = line_search.match(/#X obj \-?\d+ \-?\d+ (pddp\/helplink )?(\w*\/)?([\w|\~]+);/i);
                     if (rel_obj != null) {
-                        this.found_objects.push(rel_obj[3]);
-                        this.ref_found_objs.push(rel_obj);
+                        this.adds(rel_obj[3]);
                     } else if (/#X restore \-?\d+ \-?\d+ pd Related_objects;/i.test(line_search)) {
                         this.state = "SEARCHING_CANVAS";
+                    } else if ((/#N canvas \-?\d+ \-?\d+ \-?\d+ \-?\d+ [\S]* \-?\d+;/i.test(line_search))) {
+                        if (title != "random") {
+                            this.adds("pd");
+                        }
+                        this.state = "PD_AS_REL_OBJ";
                     }
                 },
             },
+            PD_AS_REL_OBJ: {
+                search_regex: function(line_search) {
+                    if (/#X restore \-?\d+ \-?\d+ pd;/i.test(line_search)) {
+                        this.state = "SEARCHING_OBJS";
+                    }
+                }
+            }
         },
-        dispatch(actionName, ...line_string) {
+        dispatch(actionName, line_string) {
             const action = this.transitions[this.state][actionName];
             if (action) {
-                action.call(this, ...line_string);
+                action.call(this, line_string);
+            }
+        },
+        adds(obj_title) {
+            if (!this.found_objects.includes(obj_title)) {
+                let obj_path = index.search(obj_title, {fields: {title: {}}});
+                if (obj_path.length > 0) obj_path = obj_path[0].ref;
+                this.found_objects.push(obj_title);
+                this.ref_found_objs.push(obj_path);
             }
         },
     };
     rel_objs = Object.create(machine_related_objects);
     let eval_string = data.split("\n");
     eval_string.forEach(function(l,a,i) {
-        rel_objs.dispatch('search_regex', l);
+        rel_objs.dispatch('search_regex', l.toString().replace(/\(/g, "\\\(")
+            .replace(/\)/, "\\\)"));
     });
+    ref_rel_objs = rel_objs.ref_found_objs.toString();
     rel_objs = rel_objs.found_objects;
-    rel_objs = rel_objs ? rel_objs.toString().replace( /,/g, " ") : null;
+    rel_objs = rel_objs ? rel_objs.toString().replace(/\,/g, " ") : null;
 
-    var title = path.basename(filename, ".pd"),
-        big_line = data.replace("\n", " "),
-        keywords,
-        desc;
         // We use [\s\S] to match across multiple lines...
         keywords = big_line
-            .match(/#X text \-?[0-9]+ \-?[0-9]+ KEYWORDS ([\s\S]*?);/i),
+            .match(/#X text \-?[0-9]+ \-?[0-9]+ KEYWORDS ([\s\S]*?);/i);
         desc = big_line
             .match(/#X text \-?[0-9]+ \-?[0-9]+ DESCRIPTION ([\s\S]*?);/i);
         keywords = keywords && keywords.length > 1 ? keywords[1].trim() : null;
@@ -190,34 +230,48 @@ function add_doc_to_index(filename, data) {
             desc = desc.replace(" \\,", ",");
         }
 
-    if (title.slice(-5) === "-help") {
-        title = title.slice(0, -5);
-    }
-    index_cache[index_cache.length] = [filename, title, keywords, desc, rel_objs]
+    index_cache[index_cache.length] = [filename, title, keywords, desc, rel_objs, ref_rel_objs]
         .map(index_entry_esc).join(":");
     var d = path.dirname(filename);
     index_manif.add(d);
     // Also add the parent directory to catch additions of siblings.
     index_manif.add(path.dirname(d));
-    index.addDoc({
+    index.update({
         "id": filename,
         "title": title,
         "keywords": keywords,
         "description": desc,
-        "related_objects": rel_objs
+        "related_objects": rel_objs,
+        "ref_related_objects": ref_rel_objs
+        //"body": big_line,
     });
 }
 
-function read_file(err, filename, stat) {
+function make_cache(filename) {
+    index_cache[index_cache.length] = [filename, path.basename(filename, "-help.pd"), null, null, null, null]
+        .map(index_entry_esc).join(":");
+    var d = path.dirname(filename);
+    index_manif.add(d);
+    // Also add the parent directory to catch additions of siblings.
+    index_manif.add(path.dirname(d));
+}
+
+// GB: Index all the files in Purr Data folder considering its filename, title and parent dir
+function add_doc_to_fast_index(err, filename, stat) {
     if (!err) {
-        if (filename.slice(-3) === ".pd") {
-            // AG: We MUST read the files synchronously here. This might be a
-            // performance issue on some systems, but if we don't do this then
-            // we may open a huge number of files simultaneously, causing the
-            // process to run out of file handles.
+        if (filename.slice(-8) === "-help.pd") {
             try {
-                var data = fs.readFileSync(filename, { encoding: "utf8", flag: "r" });
-                add_doc_to_index(filename, data);
+                let title = path.basename(filename, "-help.pd");
+                let regex_dir_compare = filename.match(regex_home_dir);
+                var dir = regex_dir_compare[1];
+                if (dir=="extra" && regex_dir_compare[3]) {
+                    dir = dir + "\/" + regex_dir_compare[2];
+                }
+                index.addDoc({
+                    "id": filename,
+                    "title": title,
+                    "dir": dir
+                })
             } catch (read_err) {
                 post("err: " + read_err);
             }
@@ -231,6 +285,7 @@ function read_file(err, filename, stat) {
 var index_done = false;
 var index_started = false;
 var index_start_time;
+var regex_home_dir;
 
 // Filenames for the index cache, relative to the user's homedir.
 const cache_basename = nw_os_is_windows
@@ -312,6 +367,36 @@ function make_index() {
     var doc_path = browser_doc?path.join(lib_dir, "doc"):lib_dir;
     var i = 0;
     var l = help_path.length;
+    function detail_files () {
+        post("adding details to files in " + expand_tilde(doc_path));
+        let dir = expand_tilde(doc_path).match(regex_home_dir);
+        let all_indexed_files = Object.keys(index.documentStore.docs);
+        let files_not_to_detail = all_indexed_files;
+        var files_to_detail, data;
+        if (!dir) {
+            files_to_detail = all_indexed_files;
+            files_not_to_detail = null;
+        } else {
+            dir = (dir[1]=="extra" && dir[3])?(dir[1]+"\/"+dir[2]):dir[1];
+            files_to_detail = index.search(dir,{fields: {dir: {}}}).map(obj => obj.ref);
+            files_not_to_detail = files_not_to_detail.filter(doc => !files_to_detail.includes(doc));
+        }
+        files_to_detail.forEach(function(filename,i,a) {
+            // AG: We MUST read the files synchronously here. This might be a
+            // performance issue on some systems, but if we don't do this then
+            // we may open a huge number of files simultaneously, causing the
+            // process to run out of file handles.
+            try {
+                data = fs.readFileSync(filename, { encoding: "utf8", flag: "r" });
+                add_doc_details_to_index(filename, data);
+            } catch (read_err) {
+                post("err: " + read_err);
+            }
+        });
+        if (browser_path) make_index_cont();
+        if (files_not_to_detail) files_not_to_detail.forEach(file => make_cache(file));
+        finish_index();
+    }
     function make_index_cont() {
         if (i < l) {
             var doc_path = help_path[i++];
@@ -321,13 +406,13 @@ function make_index() {
             fs.lstat(full_path, function(err, stat) {
                 if (!err) {
                     post("building help index in " + doc_path);
-                    dive(full_path, read_file, make_index_cont);
+                    detail_files();
                 } else {
                     make_index_cont();
                 }
             });
         } else {
-            finish_index();
+            // finish_index();
         }
     }
     pdsend("pd gui-busy 1");
@@ -359,12 +444,14 @@ function make_index() {
                 var keywords = e[2] ? e[2] : null;
                 var desc = e[3] ? e[3] : null;
                 var rel_obj = e[4] ? e[4] : null;
+                var ref_rel_obj = e[5] ? e[5] : null;
                 index.addDoc({
                     "id": filename,
                     "title": title,
                     "keywords": keywords,
                     "description": desc,
-                    "related_objects": rel_obj
+                    "related_objects": rel_obj,
+                    "ref_related_objects": ref_rel_obj
                 });
             }
         }
@@ -372,8 +459,9 @@ function make_index() {
     } else {
         // no index cache, or it is out of date, so (re)build it now, and
         // save the new cache along the way
-        post("building help index in " + doc_path);
-        dive(doc_path, read_file, browser_path?make_index_cont:finish_index);
+        regex_home_dir = regex_dir(lib_dir);
+        post("building help index in " + lib_dir);
+        dive(lib_dir, add_doc_to_fast_index, detail_files);
     }
     pdsend("pd gui-busy 0");
 }