Commit 7a300d56 authored by Jonathan Wilkes's avatar Jonathan Wilkes

Merge branch 'aggraef/purr-data-help-browser'

parents ddf714ba fd5fce5e
......@@ -302,6 +302,23 @@
<input type="checkbox" id="save_zoom" name="save_zoom">
<span data-i18n="prefs.gui.zoom.save_zoom"></span>
</label>
<br/><br/>
<span data-i18n="prefs.gui.browser.browser_title"></span>
<br/>
<label data-i18n="[title]prefs.gui.browser.browser_doc_tt">
<input type="checkbox" id="browser_doc" name="browser_doc">
<span data-i18n="prefs.gui.browser.browser_doc"></span>
</label>
<br/>
<label data-i18n="[title]prefs.gui.browser.browser_path_tt">
<input type="checkbox" id="browser_path" name="browser_path">
<span data-i18n="prefs.gui.browser.browser_path"></span>
</label>
<br/>
<label data-i18n="[title]prefs.gui.browser.browser_init_tt">
<input type="checkbox" id="browser_init" name="browser_init">
<span data-i18n="prefs.gui.browser.browser_init"></span>
</label>
</div>
</div>
......@@ -396,8 +413,8 @@ function get_gui_preset() {
return document.getElementById("gui_preset").selectedOptions[0].value;
}
function get_save_zoom() {
return +document.getElementById("save_zoom").checked;
function get_bool_elem(elem) {
return +document.getElementById(elem).checked;
}
// startup config data
......@@ -606,9 +623,10 @@ function apply(save_prefs) {
midi_use_alsa ? get_attr("midi-outdev-names", attrs).length : 0
);
// Send the gui prefs (currently just the name of the gui preset and the
// status of the save-zoom toggle) to Pd
pdgui.pdsend("pd gui-prefs", get_gui_preset(), get_save_zoom());
// Send the gui prefs (currently just the name of the gui preset, the
// status of the save-zoom toggle and various options related to the help
// browser) to Pd
pdgui.pdsend("pd gui-prefs", get_gui_preset(), get_bool_elem("save_zoom"), get_bool_elem("browser_doc"), get_bool_elem("browser_path"), get_bool_elem("browser_init"));
// Send the startup config data to Pd
pdgui.pdsend.apply(null, ["pd path-dialog", startup_use_stdpath, startup_verbose].concat(get_path_array()));
......@@ -847,7 +865,7 @@ function midi_prefs_callback(attrs) {
pdgui.resize_window(pd_object_callback);
}
function gui_prefs_callback(name, save_zoom) {
function gui_prefs_callback(name, save_zoom, browser_doc, browser_path, browser_init) {
var s = document.getElementById("gui_preset"),
i;
for (i = 0; i < s.options.length; i++) {
......@@ -857,6 +875,9 @@ function gui_prefs_callback(name, save_zoom) {
}
}
document.getElementById("save_zoom").checked = !!save_zoom;
document.getElementById("browser_doc").checked = !!browser_doc;
document.getElementById("browser_path").checked = !!browser_path;
document.getElementById("browser_init").checked = !!browser_init;
}
// startup settings
......
......@@ -4,27 +4,18 @@
<link id="page_style" rel="stylesheet"
type="text/css" href="css/default.css">
<title>Pd Search Engine</title>
<script type="text/javascript" src="./elasticlunr.js"></script>
<script type="text/javascript" src="./console_search.js"></script>
<script>
"use strict";
var pdgui = require("./pdgui.js");
var fs = require("fs");
var path = require("path");
var dive = require("./dive.js"); // small module to recursively search dirs
var l = pdgui.get_local_string;
var index = elasticlunr();
var index;
pdgui.skin.apply(window);
index.addField("title");
index.addField("keywords");
index.addField("description");
//index.addField("body");
index.addField("path");
index.setRef("id");
var filetypes = [".pd", ".txt", ".htm", ".html", ".pdf"];
// Table of Contents to start with
......@@ -159,54 +150,6 @@ function translate_form() {
}
}
function add_doc_to_index(filename, data) {
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),
desc = big_line
.match(/#X text \-?[0-9]+ \-?[0-9]+ DESCRIPTION ([\s\S]*?);/i);
keywords = keywords && keywords.length > 1 ? keywords[1].trim() : null;
desc = desc && desc.length > 1 ? desc[1].trim() : null;
// Remove the Pd escapes for commas
desc = desc ? desc.replace(" \\,", ",") : null;
if (desc) {
// format Pd's "comma atoms" as normal commas
desc = desc.replace(" \\,", ",");
}
if (title.slice(-5) === "-help") {
title = title.slice(0, -5);
}
index.addDoc({
"id": filename,
"title": title,
"keywords": keywords,
"description": desc
//"body": big_line,
});
}
function read_file(err, filename, stat) {
if (!err) {
if (filename.slice(-3) === ".pd") {
fs.readFile(filename, { encoding: "utf8", flag: "r" },
function(read_err, data) {
if (!read_err) {
add_doc_to_index(filename, data);
} else {
pdgui.post("err: " + read_err);
}
}
);
}
} else {
pdgui.post("err: " + err);
}
}
function click_toc(dir) {
document.getElementById("search_text").value = dir;
doc_search();
......@@ -251,18 +194,13 @@ function display_toc() {
});
}
function finish_build() {
function finish_build(idx) {
index = idx;
document.getElementById("search_text").disabled = false;
clear_results();
display_toc();
}
function build_index() {
var doc_path = path.join(pdgui.get_lib_dir(), "doc");
pdgui.post("doc path is " + doc_path);
dive(doc_path, read_file, finish_build);
}
function clear_results() {
document.getElementById("results").innerHTML = "";
}
......@@ -528,7 +466,7 @@ function register_window_id(id, attrs) {
document.getElementById("search_text").disabled = true;
document.getElementById("file_browser").setAttribute("nwworkingdir",
doc_path); // Probably need a doc getter in pdgui
build_index();
pdgui.build_index(finish_build);
}
function display_no_results() {
......
......@@ -407,6 +407,15 @@
"zoom": {
"save_zoom": "Speichern/Laden der Vergrößerung im Patch",
"save_zoom_tt": "Speichere die aktuelle Vergrößerung mit dem Patch und stelle diese beim Laden des Patches wieder her"
},
"browser": {
"browser_title": "Hilfe-Browser-Einstellungen (WARNUNG: Änderungen können Startup-Zeiten beeinflussen!)",
"browser_doc": "Hilfe-Browser durchsucht nur den doc-Ordner",
"browser_doc_tt": "Der Hilfe-Browser durchkämmt nur Hilfe-Patches im doc-Ordner nach Suchbegriffen (schneller)",
"browser_path": "Hilfe-Browser durchsucht auch den Hilfe-Pfad",
"browser_path_tt": "Der Hilfe-Browser durchkämmt auch Hilfe-Patches im benutzerdefinierten Hilfe-Pfad nach Suchbegriffen (langsamer)",
"browser_init": "Erstelle den Hilfe-Index beim Programmstart",
"browser_init_tt": "Falls aktiviert, erstelle den Index für den Hilfe-Browser bereits beim Programmstart"
}
},
"audio": {
......
......@@ -408,6 +408,15 @@
"zoom": {
"save_zoom": "save/load zoom level with patch",
"save_zoom_tt": "Save the current zoom level with the patch and restore it when reloading the patch"
},
"browser": {
"browser_title": "Help browser settings (WARNING: changing these may affect startup times!)",
"browser_doc": "help browser only searches the doc folder",
"browser_doc_tt": "Only scan help patches in the doc folder for searchable keywords (faster)",
"browser_path": "help browser also searches the help path",
"browser_path_tt": "Also scan help patches in the user-defined help path for searchable keywords (slower)",
"browser_init": "prepare the help index at application start",
"browser_init_tt": "If checked, prepare the index for the help browser already when the application starts"
}
},
"audio": {
......
......@@ -2,6 +2,7 @@
var pwd;
var lib_dir;
var help_path, browser_doc, browser_path, browser_init;
var pd_engine_id;
exports.set_pwd = function(pwd_string) {
......@@ -26,6 +27,19 @@ exports.set_pd_engine_id = function (id) {
exports.defunkify_windows_path = defunkify_windows_path;
function gui_set_browser_config(doc_flag, path_flag, init_flag, helppath) {
// post("gui_set_browser_config: " + helppath.join(":"));
browser_doc = doc_flag;
browser_path = path_flag;
browser_init = init_flag;
help_path = helppath;
// AG: Start building the keyword index for dialog_search.html. We do this
// here so that we can be sure that lib_dir and help_path are known already.
// (This may also be deferred until the browser is launched for the first
// time, depending on the value of browser_init.)
if (browser_init == 1) make_index();
}
function gui_set_lib_dir(dir) {
lib_dir = dir;
}
......@@ -60,10 +74,140 @@ exports.set_focused_patchwin = function(cid) {
last_focused = cid;
}
// Keyword index (cf. dialog_search.html)
var fs = require("fs");
var path = require("path");
var dive = require("./dive.js"); // small module to recursively search dirs
var elasticlunr = require("./elasticlunr.js"); // lightweight full-text search engine in JavaScript, cf. https://github.com/weixsong/elasticlunr.js/
var index = elasticlunr();
index.addField("title");
index.addField("keywords");
index.addField("description");
//index.addField("body");
index.addField("path");
index.setRef("id");
function add_doc_to_index(filename, data) {
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),
desc = big_line
.match(/#X text \-?[0-9]+ \-?[0-9]+ DESCRIPTION ([\s\S]*?);/i);
keywords = keywords && keywords.length > 1 ? keywords[1].trim() : null;
desc = desc && desc.length > 1 ? desc[1].trim() : null;
// Remove the Pd escapes for commas
desc = desc ? desc.replace(" \\,", ",") : null;
if (desc) {
// format Pd's "comma atoms" as normal commas
desc = desc.replace(" \\,", ",");
}
if (title.slice(-5) === "-help") {
title = title.slice(0, -5);
}
index.addDoc({
"id": filename,
"title": title,
"keywords": keywords,
"description": desc
//"body": big_line,
});
}
function read_file(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.
try {
var data = fs.readFileSync(filename, { encoding: "utf8", flag: "r" });
add_doc_to_index(filename, data);
} catch (read_err) {
post("err: " + read_err);
}
}
} else {
// AG: Simply ignore missing/unreadable files and directories.
// post("err: " + err);
}
}
var index_done = false;
var index_started = false;
function finish_index() {
index_done = true;
post("finished building help index");
}
// AG: pilfered from https://stackoverflow.com/questions/21077670
function expand_tilde(filepath) {
if (filepath[0] === '~') {
return path.join(process.env.HOME, filepath.slice(1));
}
return filepath;
}
// AG: This is supposed to be executed only once, after lib_dir has been set.
// Note that dive() traverses lib_dir asynchronously, so we report back in
// finish_index() when this is done.
function make_index() {
var doc_path = browser_doc?path.join(lib_dir, "doc"):lib_dir;
var i = 0;
var l = help_path.length;
function make_index_cont() {
if (i < l) {
var doc_path = help_path[i++];
// AG: These paths might not exist, ignore them in this case. Also
// note that we need to expand ~ here.
var full_path = expand_tilde(doc_path);
fs.lstat(full_path, function(err, stat) {
if (!err) {
post("building help index in " + doc_path);
dive(full_path, read_file, make_index_cont);
} else {
make_index_cont();
}
});
} else {
finish_index();
}
}
index_started = true;
post("building help index in " + doc_path);
dive(doc_path, read_file, browser_path?make_index_cont:finish_index);
}
// AG: This is called from dialog_search.html with a callback that expects to
// receive the finished index as its sole argument. We also build the index
// here if needed, using make_index, then simply wait until make_index
// finishes and finally invoke the callback on the resulting index.
function build_index(cb) {
function build_index_worker() {
if (index_done == true) {
cb(index);
} else {
setTimeout(build_index_worker, 500);
}
}
if (index_started == false) {
make_index();
}
build_index_worker();
}
exports.build_index = build_index;
// Modules
var fs = require("fs"); // for fs.existsSync
var path = require("path"); // for path.dirname path.extname path.join
var cp = require("child_process"); // for starting core Pd from GUI in OSX
var parse_svg_path = require("./parse-svg-path.js");
......@@ -4964,9 +5108,9 @@ function gui_midi_properties(gfxstub, sys_indevs, sys_outdevs,
}
}
function gui_gui_properties(dummy, name, save_zoom) {
function gui_gui_properties(dummy, name, save_zoom, browser_doc, browser_path, browser_init) {
if (dialogwin["prefs"] !== null) {
dialogwin["prefs"].window.gui_prefs_callback(name, save_zoom);
dialogwin["prefs"].window.gui_prefs_callback(name, save_zoom, browser_doc, browser_path, browser_init);
}
}
......
......@@ -75,18 +75,21 @@ static void glob_perf(t_pd *dummy, float f)
sys_perf = (f != 0);
}
extern int sys_zoom;
extern int sys_zoom, sys_browser_doc, sys_browser_path, sys_browser_init;
extern t_symbol *sys_gui_preset;
static void glob_gui_prefs(t_pd *dummy, t_symbol *s, float f)
static void glob_gui_prefs(t_pd *dummy, t_symbol *s, float f, float f2, float f3, float f4)
{
sys_gui_preset = s;
sys_zoom = !!(int)f;
sys_browser_doc = !!(int)f2;
sys_browser_path = !!(int)f3;
sys_browser_init = !!(int)f4;
}
/* just the gui-preset and the save-zoom toggle for now */
/* just the gui-preset, the save-zoom toggle and various help browser options for now */
static void glob_gui_properties(t_pd *dummy)
{
gui_vmess("gui_gui_properties", "xsi", 0, sys_gui_preset->s_name, sys_zoom);
gui_vmess("gui_gui_properties", "xsiiii", 0, sys_gui_preset->s_name, sys_zoom, sys_browser_doc, sys_browser_path, sys_browser_init);
}
// ths one lives inside g_editor so that it can access the clipboard
......@@ -172,7 +175,7 @@ void glob_init(void)
class_addmethod(glob_pdobject, (t_method)glob_clipboard_text,
gensym("clipboardtext"), A_FLOAT, 0);
class_addmethod(glob_pdobject, (t_method)glob_gui_prefs,
gensym("gui-prefs"), A_SYMBOL, A_FLOAT, 0);
gensym("gui-prefs"), A_SYMBOL, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
class_addmethod(glob_pdobject, (t_method)glob_gui_properties,
gensym("gui-properties"), 0);
class_addmethod(glob_pdobject, (t_method)glob_recent_files,
......
......@@ -40,7 +40,7 @@
#define snprintf sprintf_s
#endif
int sys_defeatrt, sys_zoom;
int sys_defeatrt, sys_zoom, sys_browser_doc = 1, sys_browser_path, sys_browser_init;
t_symbol *sys_flags = &s_;
void sys_doflags( void);
......@@ -669,6 +669,12 @@ void sys_loadpreferences( void)
sscanf(prefbuf, "%d", &sys_defeatrt);
if (sys_getpreference("savezoom", prefbuf, MAXPDSTRING))
sscanf(prefbuf, "%d", &sys_zoom);
if (sys_getpreference("browser_doc", prefbuf, MAXPDSTRING))
sscanf(prefbuf, "%d", &sys_browser_doc);
if (sys_getpreference("browser_path", prefbuf, MAXPDSTRING))
sscanf(prefbuf, "%d", &sys_browser_path);
if (sys_getpreference("browser_init", prefbuf, MAXPDSTRING))
sscanf(prefbuf, "%d", &sys_browser_init);
if (sys_getpreference("guipreset", prefbuf, MAXPDSTRING))
{
char preset_buf[MAXPDSTRING];
......@@ -808,6 +814,12 @@ void glob_savepreferences(t_pd *dummy)
sys_putpreference("defeatrt", buf1);
sprintf(buf1, "%d", sys_zoom);
sys_putpreference("savezoom", buf1);
sprintf(buf1, "%d", sys_browser_doc);
sys_putpreference("browser_doc", buf1);
sprintf(buf1, "%d", sys_browser_path);
sys_putpreference("browser_path", buf1);
sprintf(buf1, "%d", sys_browser_init);
sys_putpreference("browser_init", buf1);
sys_putpreference("guipreset", sys_gui_preset->s_name);
sys_putpreference("flags",
(sys_flags ? sys_flags->s_name : ""));
......
......@@ -285,11 +285,13 @@ void glob_forward_files_from_secondary_instance(void)
}
extern void glob_recent_files(t_pd *dummy);
extern int sys_browser_doc, sys_browser_path, sys_browser_init;
/* this is called from main() in s_entry.c */
int sys_main(int argc, char **argv)
{
int i, noprefs;
t_namelist *nl;
sys_externalschedlib = 0;
sys_extraflags = 0;
sys_gui_preset = gensym("default");
......@@ -325,6 +327,17 @@ int sys_main(int argc, char **argv)
gui_vmess("gui_set_gui_preset", "s", sys_gui_preset->s_name);
/* send the recent files list */
glob_recent_files(0);
/* AG: send the browser config; this must come *after* gui_set_lib_dir
so that the lib_dir is available when help indexing starts */
gui_start_vmess("gui_set_browser_config", "iii",
sys_browser_doc, sys_browser_path, sys_browser_init);
gui_start_array();
for (nl = sys_helppath; nl; nl = nl->nl_next)
{
gui_s(nl->nl_string);
}
gui_end_array();
gui_end_vmess();
if (sys_externalschedlib)
return (sys_run_scheduler(sys_externalschedlibname,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment