Skip to content
Permalink
Browse files

from ketmar: added ".gitignore" processor; adrdox can be called from …

…any directory; it will look for template files at binary's dir
  • Loading branch information
adamdruppe committed Feb 26, 2018
1 parent 2d06c72 commit a96e78432a48a091c66b2d72715dd128e7a0dc2f
Showing with 204 additions and 2 deletions.
  1. +1 −1 comment.d
  2. +201 −1 doc2.d
  3. +2 −0 stemmer.d
@@ -33,7 +33,7 @@ static struct MyOutputRange {

void putTag(in char[] s) {
foreach(ch; s) {
assert(s);
assert(s.length);
assert(s.indexOf("</body>") == -1);
}
(*output) ~= s;
202 doc2.d
@@ -35,6 +35,33 @@ import std.algorithm :sort, canFind;
import std.string;
import std.conv : to;

// returns empty string if file not found
string findStandardFile(bool dofail=true) (string stdfname) {
import std.file : exists, thisExePath;
import std.path : buildPath, dirName;
if (!stdfname.exists) {
if (stdfname.length && stdfname[0] != '/') {
string newname = buildPath(thisExePath.dirName, stdfname);
if (newname.exists) return newname;
}
static if (dofail) throw new Exception("standard file '" ~stdfname ~ "' not found!");
}
return stdfname;
}

void copyStandardFileTo(bool timecheck=true) (string destname, string stdfname) {
import std.file;
if (exists(destname)) {
static if (timecheck) {
if (timeLastModified(destname) >= timeLastModified(findStandardFile(stdfname))) return;
} else {
return;
}
}
copy(findStandardFile(stdfname), destname);
}


// FIXME: make See Also automatically list dittos that are not overloads

enum skip_undocumented = true;
@@ -616,7 +643,7 @@ Document writeHtml(Decl decl, bool forReal = true) {

auto document = new Document();
import std.file;
document.parseUtf8(readText(skeletonFile), true, true);
document.parseUtf8(readText(findStandardFile(skeletonFile)), true, true);
document.title = title ~ " (" ~ decl.fullyQualifiedName ~ ")";

auto content = document.requireElementById("page-content");
@@ -2428,6 +2455,164 @@ ModuleDecl[string] modulesByName;

string specialPreprocessor;

// simplified ".gitignore" processor
final class GitIgnore {
string[] masks; // on each new dir, empty line is added to masks

void loadGlobalGitIgnore () {
import std.path;
import std.stdio;
try {
foreach (string s; File("~/.gitignore_global".expandTilde).byLineCopy) {
if (isComment(s)) continue;
masks ~= trim(s);
}
} catch (Exception e) {} // sorry
try {
foreach (string s; File("~/.adrdoxignore_global".expandTilde).byLineCopy) {
if (isComment(s)) continue;
masks ~= trim(s);
}
} catch (Exception e) {} // sorry
}

void loadGitIgnore (const(char)[] dir) {
import std.path;
import std.stdio;
masks ~= null;
try {
foreach (string s; File(buildPath(dir, ".gitignore").expandTilde).byLineCopy) {
if (isComment(s)) continue;
masks ~= trim(s);
}
} catch (Exception e) {} // sorry
try {
foreach (string s; File(buildPath(dir, ".adrdoxignore").expandTilde).byLineCopy) {
if (isComment(s)) continue;
masks ~= trim(s);
}
} catch (Exception e) {} // sorry
}

// unload latest gitignore
void unloadGitIgnore () {
auto ol = masks.length;
while (masks.length > 0 && masks[$-1] !is null) masks = masks[0..$-1];
if (masks.length > 0 && masks[$-1] is null) masks = masks[0..$-1];
if (masks.length != ol) {
//writeln("removed ", ol-masks.length, " lines");
masks.assumeSafeAppend; //hack!
}
}

bool match (string fname) {
import std.path;
import std.stdio;
if (masks.length == 0) return false;
//writeln("gitignore checking: <", fname, ">");

bool xmatch (string path, string mask) {
if (mask.length == 0 || path.length == 0) return false;
import std.string : indexOf;
if (mask.indexOf('/') < 0) return path.baseName.globMatch(mask);
int xpos = cast(int)path.length-1;
while (xpos >= 0) {
while (xpos >= 0 && path[xpos] != '/') --xpos;
if (mask[0] == '/') {
if (xpos+1 < path.length && path[xpos+1..$].globMatch(mask)) return true;
} else {
if (path[xpos..$].globMatch(mask)) return true;
}
--xpos;
}
return false;
}

string curname = fname.baseName;
int pos = cast(int)masks.length-1;
// local dir matching
while (pos >= 0 && masks[pos] !is null) {
//writeln(" [", masks[pos], "]");
if (xmatch(curname, masks[pos])) {
//writeln(" LOCAL HIT: [", masks[pos], "]: <", curname, ">");
return true;
}
if (masks[pos][0] == '/' && xmatch(curname, masks[pos][1..$])) return true;
--pos;
}
curname = fname;
while (pos >= 0) {
if (masks[pos] !is null) {
//writeln(" [", masks[pos], "]");
if (xmatch(curname, masks[pos])) {
//writeln(" HIT: [", masks[pos], "]: <", curname, ">");
return true;
}
}
--pos;
}
return false;
}

static:
inout(char)[] trim (inout(char)[] s) {
while (s.length > 0 && s[0] <= ' ') s = s[1..$];
while (s.length > 0 && s[$-1] <= ' ') s = s[0..$-1];
return s;
}

bool isComment (const(char)[] s) {
s = trim(s);
return (s.length == 0 || s[0] == '#');
}
}


string[] scanFiles (string basedir) {
import std.file : isDir;
import std.path;

string[] res;

auto gi = new GitIgnore();
gi.loadGlobalGitIgnore();

void scanSubDir(bool checkdir=true) (string dir) {
import std.file;
static if (checkdir) {
string d = dir;
if (d.length > 1 && d[$-1] == '/') d = d[0..$-1];
if (gi.match(d)) {
//writeln("DIR SKIP: <", dir, ">");
return;
}
}
gi.loadGitIgnore(dir);
scope(exit) gi.unloadGitIgnore();
foreach (DirEntry de; dirEntries(dir, SpanMode.shallow)) {
try {
if (de.isDir) { scanSubDir(de.name); continue; }
if (de.baseName.length == 0) continue; // just in case
if (de.baseName[0] == '.') continue; // skip hidden files
if (!de.baseName.globMatch("*.d")) continue;
if (/*de.isFile &&*/ !gi.match(de.name)) {
//writeln(de.name);
res ~= de.name;
}
} catch (Exception e) {} // some checks (like `isDir`) can throw
}
}

basedir = basedir.expandTilde.absolutePath;
if (basedir.isDir) {
scanSubDir!false(basedir);
} else {
res ~= basedir;
}
return res;
}


void main(string[] args) {
import std.stdio;
import std.path : buildPath;
@@ -2482,6 +2667,16 @@ void main(string[] args) {
if(locateSymbol is null) {
import std.file;

if (!exists(skeletonFile) && findStandardFile!false("skeleton-default.html").length)
copyStandardFileTo!false(skeletonFile, "skeleton-default.html");

if (!exists(outputDirectory))
mkdir(outputDirectory);

copyStandardFileTo(outputDirectory ~ "style.css", "style.css");
copyStandardFileTo(outputDirectory ~ "script.js", "script.js");

/*
if(!exists(skeletonFile) && exists("skeleton-default.html"))
copy("skeleton-default.html", skeletonFile);
@@ -2491,6 +2686,7 @@ void main(string[] args) {
copy("style.css", outputDirectory ~ "style.css");
if(!exists(outputDirectory ~ "script.js") || (timeLastModified(outputDirectory ~ "script.js") < timeLastModified("script.js")))
copy("script.js", outputDirectory ~ "script.js");
*/
}

// FIXME: maybe a zeroth path just grepping for a module declaration in located files
@@ -2602,14 +2798,18 @@ void main(string[] args) {
}

string[] generateFiles;
foreach (arg; args) generateFiles ~= scanFiles(arg);
/*
foreach(argIdx, arg; args) {
if(arg != "-" && std.file.isDir(arg))
foreach(string name; std.file.dirEntries(arg, "*.d", std.file.SpanMode.breadth))
generateFiles ~= name;
else
generateFiles ~= arg;
}
*/
args = generateFiles;
//{ import std.stdio; foreach (fn; args) writeln(fn); } assert(0);


// Process them all first so name-lookups have more chance of working
@@ -243,12 +243,14 @@ public struct PorterStemmer
private void step1ab()
{
if( m_b[ m_k ] == 's' )
{
if( ends( "sses" ) )
m_k = m_k - 2;
else if( ends( "ies" ) )
setto( "i" );
else if( m_b[ m_k - 1 ] != 's' )
m_k--;
}
if( ends( "eed" ) )
{
if( m() > 0 )

0 comments on commit a96e784

Please sign in to comment.
You can’t perform that action at this time.