#include <dirent.h>
#include <unistd.h>
#include <fstream>
#include <cstdio>
#include <vector>
#include <map>
#include <sstream>
#include <string.h>
#include <stdlib.h>
#include "bloputils.h"
#include "blop_bookkeeper.h"
#include "help.h"
#include "pstream.h"
#include "config.h"
namespace blop
{
using namespace std;
bool file_exists(const string &filename)
{
ifstream f(filename.c_str());
return f.good();
}
string get_title(string fullfilename)
{
string entry = fullfilename;
{
string::size_type hashmark = fullfilename.find('#');
if(hashmark != string::npos) fullfilename.erase(hashmark,string::npos);
ifstream fff(fullfilename.c_str());
string line;
while(getline(fff,line))
{
if(line.find("<center class=title><b>") != string::npos)
{
getline(fff,line);
entry = line;
break;
}
}
}
return entry;
}
void fill_helpindex(const string &filename, map<string,vector<pair<string,string> > > &help_index,
const string &docdir)
{
ifstream indexfile(filename.c_str());
string line;
while(getline(indexfile,line))
{
istringstream linestr(line);
vector<string> keywords,fns;
string str;
int what = 0;
while(linestr>>str)
{
if(str == ":") ++what;
else
{
if(what == 0) keywords.push_back(str);
else fns.push_back(str);
}
}
for(vector<string>::size_type i=0; i<keywords.size(); ++i)
{
for(vector<string>::size_type j=0; j<fns.size(); ++j)
{
string fullfilename;
if(fns[j][0] != '/') fullfilename = docdir + "/" + fns[j];
else fullfilename = fns[j];
pair<string,string> entry;
entry.first = get_title(fullfilename);
entry.second = fullfilename;
help_index[keywords[i]].push_back(entry);
}
}
}
}
void show_helpfile(const string &helpfilename)
{
system((string("blop-helpviewer ") + helpfilename).c_str());
}
void help(var topic, var file_name)
{
bool make_search = false;
if(topic[0] == '?')
{
make_search = true;
topic(0,0) = "";
}
const char *docdir = getenv("BLOP_DOCDIR");
if(docdir == 0) docdir = BLOP_DOCDIR;
static map<string,vector<pair<string,string> > > help_index;
if(help_index.empty())
{
char indexfilename[1000];
sprintf(indexfilename,"%s/help-index",docdir);
fill_helpindex(indexfilename,help_index,docdir);
if(const char *home = getenv("HOME"))
{
string hi = string(home) + "/.blop/help-index";
fill_helpindex(hi,help_index,docdir);
}
}
if(topic == "keywords")
{
cout<<"Available keywords: "<<endl;
cout<<"^^^^^^^^^^^^^^^^^^^ "<<endl;
for(map<string,vector<pair<string,string> > >::iterator i=help_index.begin();
i != help_index.end(); ++i)
{
cout<<" "<<(*i).first<<endl;
}
return;
}
string topic_str = topic.str();
for(unsigned int i=0; i<topic_str.size(); ++i)
{
if(topic_str[i] == '\'') topic_str[i] = ' ';
}
{
string fn = string(docdir) + "/documentation/" + topic_str;
if( (topic_str.find(".h") == topic_str.size()-2 ||
topic_str.find(".cc") == topic_str.size()-3) &&
file_exists(fn+".html") )
{
show_helpfile(fn+".html");
return;
}
if(topic_str.find(".html") == topic_str.size()-5 && file_exists(fn))
{
show_helpfile(fn);
return;
}
}
if(help_index.find(topic_str) != help_index.end() &&
help_index[topic_str].size() == 1 && !make_search)
{
show_helpfile(help_index[topic_str][0].second);
return;
}
string helpfilename;
if(file_name.str() == "") helpfilename = BLOP.tmpfile("XXXXXX.html");
else helpfilename = file_name.str();
ofstream helpfile(helpfilename.c_str());
helpfile<<"<html><body>"<<endl;
bool found_in_index = false;
if(help_index.find(topic_str) != help_index.end())
{
helpfile<<"<h1>The following files are dedicated for the keyword '"<<topic_str<<"':</h1><br>"<<endl;
helpfile<<"<ul>"<<endl;
for(unsigned int i=0; i<help_index[topic_str].size(); ++i)
{
helpfile<<"<li><a href=\""<<help_index[topic_str][i].second
<<"\">"<<help_index[topic_str][i].first<<"</a>"<<endl;
}
helpfile<<"</ul>"<<endl;
found_in_index = true;
}
else
{
helpfile<<"<h1>No docfiles are dedicated for the keyword '"<<topic_str<<"'</h1><br>"<<endl;
}
helpfile<<"<hr>"<<endl;
bool found_by_grep = false;
if(make_search || !found_in_index)
{
vector<string> subdirs;
subdirs.push_back(string(docdir) + "/documentation");
subdirs.push_back(string(docdir) + "/tutorial");
subdirs.push_back(string(docdir) + "/user-examples");
for(unsigned int i=0; i<subdirs.size(); ++i)
{
DIR *dir = opendir(subdirs[i].c_str());
if(dir == 0)
{
cerr<<"Could not open directory \""<<subdirs[i]<<"\""<<endl;
continue;
}
dirent *f;
while( (f=readdir(dir)) != 0)
{
bool ok = false;
if(strstr(f->d_name,".html") != 0) ok = true;
if(subdirs[i] == string(docdir) + "/user-examples") ok = true;
if(!ok) continue;
string fullfilename = subdirs[i] + "/" + string(f->d_name);
string grepcmd = string("grep -E '") + topic_str + string("' ") + fullfilename;
ipstream grep(grepcmd);
string line, result = "<pre>";
while(getline(grep,line))
{
string lineno = "";
string::size_type beg;
if((beg = line.find("<a name=\"__line")) != string::npos)
{
string::size_type end = line.find('>',beg);
lineno = line.substr(beg+9,end-beg-10);
line.replace(beg,end+5-beg,"");
}
for(unsigned int i=0; i<line.length(); ++i)
{
if (line[i] == '<') { line.replace(i,1,"<"); i += 3; }
else if(line[i] == '>') { line.replace(i,1,">"); i += 3; }
}
{
string::size_type pos = 0, res;
while((res = line.find(topic_str,pos)) != string::npos)
{
string newstr = "<span style=\"color: #FF0000;\">" + topic_str + "</span>";
line.replace(res,topic_str.length(),newstr);
pos = res + newstr.length();
}
}
if(lineno != "")
{
result += "<a href=\"" + fullfilename + "#" + lineno + "\">=></a> " + line+ "\n";
}
else
{
result += "=> " + line + "\n";
}
}
result += "</pre>";
if(grep.close() == 0)
{
if(found_by_grep == false)
{
helpfile << "<h1>The keyword '"<<topic_str<<"' was found in the following files: </h1><br>"
<< endl;
helpfile << "<ul>"<<endl;
}
found_by_grep = true;
string entry = get_title(fullfilename);
helpfile<<"<li><dl><dt><a href=\""<<fullfilename<<"\"> "<<entry;
if(entry != fullfilename) helpfile<<" ("<<fullfilename<<")";
helpfile<<"</a></dt>"<<endl;
helpfile<<" <dd>\n"<<result<<"</dd></dl>"<<endl;
}
}
}
if(found_by_grep) helpfile<<"</ul>"<<endl;
else helpfile<<"<h1>The keyword '"<<topic_str<<"' was not found in any other files</h1>"<<endl;
}
helpfile << "</body></html>"<<endl;
helpfile.close();
if(found_in_index == false && found_by_grep == false)
{
cerr<<"Your topic '"<<topic_str<<"' was not found"<<endl;
return;
}
show_helpfile(helpfilename);
}
}