*! version 1.5.4 *! Doug Hemken *! 27 March 2018 // ISSUES // ====== // wrapper with dyndoc, pandoc // better, more extensive preamble, e.g. linesize, other options? // NOGRaph option // ignore executable code within non-executable fence capture program drop stmd2dyn capture mata: mata clear program define stmd2dyn, rclass syntax anything(name=infile), [SAVing(string) replace] local infile = ustrtrim(usubinstr(`"`infile'"', `"""', "", .)) *display `"infile is `infile'"' confirm file `"`infile'"' *display "infile confirmed" if ("`saving'" == "" ) { mata:(void)pathchangesuffix("`infile'", "dyn", "saving", 0) mata: (void)st_local("saving", pathjoin("`c(pwd)'", `"`saving'"')) } mata: (void)pathresolve("`c(pwd)'", `"`saving'"', "saving") *display `"saving `saving'"' local issame = 0 mata: (void)filesarethesame("`infile'", "`saving'", "issame") if ("`issame'" == "1") { display in error "target file can not be the same as the source file" exit 602 } if ("`replace'"=="") { confirm new file "`saving'" } * Read in file mata: X=docread("`infile'") * Then identify code blocks and tags mata: fenceinfo = _fence_info(X) // fences mata: infotags = _info_tags(X) // retrieve infotags mata: tagmatchs = _tag_match(infotags) // parse infotags mata: dotags = _dd_do(fenceinfo, tagmatchs) // generate <> * Identify display directives mata: X = _inline_code(X) * assemble pieces of a dyndoc mata: document = _stitch(X, fenceinfo, dotags) * Write out the result mata: saving = st_local("saving") mata: docwrite(saving, document) display " {text:Output saved as {it:`saving'}}" * Finish up return local outfile "`saving'" end mata string colvector docread(string scalar filename) { fh = fopen(filename, "r") string colvector document document= J(0,1,"") while ((line=fget(fh))!=J(0,0,"")) { document = (document\line) } fclose(fh) return(document) } void function docwrite(string scalar filename, /// string colvector document) { unlink(filename) fh = fopen(filename, "w") for (i=1; i<=length(document); i++) { fput(fh, document[i]) } fclose(fh) } real matrix function _fence_info(string colvector X) { codefence = "^( ? ? ?)(```+|~~~+)([ ]*)$" infofence = "^( ? ? ?)(```+|~~~+)\{?s(tata)?\/?(,.*)?\}?$" fence = ustrregexm(X, codefence) codebegin = ustrregexm(X, infofence) fence = fence + codebegin prespace = J(rows(X),1,.) fencel = J(rows(X),1,.) cb = 0 cbfl = 0 for (i=1; i<=rows(X); i++) { if (ustrregexm(X[i,1], infofence)) { prespace[i] = ustrlen(ustrregexs(1)) fencel[i] = ustrlen(ustrregexs(2)) cb = 1 cbfl = fencel[i] } else if (ustrregexm(X[i,1], codefence)) { prespace[i] = ustrlen(ustrregexs(1)) fencel[i] = ustrlen(ustrregexs(2)) if (cb & fencel[i]>=cbfl) { codebegin[i] = -1 cb = 0 cbfl = 0 } } } return(fence,codebegin,prespace,fencel) } string colvector function _info_tags(string colvector X) { infofence = "^( ? ? ?)(```+|~~~+)\{?s(tata)?\/?(,.*)?\}?$" //infofence infotags = J(rows(X),1,"") for (i=1; i<=rows(X); i++) { if (ustrregexm(X[i,1], infofence)) { infotags[i] = ustrregexs(4) } } return(infotags) } real matrix function _tag_match(string colvector infotags) { codeopts = ustrregexm(infotags, ",") noeval = ustrregexm(infotags, "eval=FALSE") noecho1 = ustrregexm(infotags, "echo=FALSE") noecho2 = ustrregexm(infotags, "\/") noecho = noecho1+noecho2 noresults = ustrregexm(infotags, "results=FALSE") noprompt = ustrregexm(infotags, "noprompt=TRUE") return(codeopts, noeval, noecho, noresults, noprompt) } string colvector function _dd_do(real matrix fenceinfo, real matrix tagmatch) { dotags = J(rows(fenceinfo),1,"") for (i=1; i<=rows(fenceinfo); i++) { if (fenceinfo[i,2]==1) { if (sum(tagmatch[i,.])==0) dotags[i,1]=("<>") else if (tagmatch[i,3]==1) { if (tagmatch[i,4]==0) dotags[i,1]=("<>") else if (tagmatch[i,4]==1) dotags[i,1]=("<>") } else if (tagmatch[i,3]==0 & tagmatch[i,4]==1) dotags[i,1]=("<>") else if (tagmatch[i,5]==1) dotags[i,1]=("<>") } else if (fenceinfo[i,2]==-1) dotags[i,1]=("<>") else dotags[i,1]=("") } return(dotags) } string colvector function _gr_preamble() { GR = "<>"\ "capture graph describe Graph"\ "tempname gdate"\ `"local \`gdate' = "\`r(command_date)' \`r(command_time)'" "'\ "<>" return(GR) } string colvector function _gr_link() { GL = `"<>"' \ `"capture graph describe Graph"' \ `"local checkdate = "\`r(command_date)' \`r(command_time)'" "' \ `"<>"' \ `"<>"' \ `"<>"' \ `"<>"' \ `"<>"' \ `"local \`gdate' = "\`r(command_date)' \`r(command_time)'""' \ `"<>"' return(GL) } string colvector function _stitch(string colvector X, real matrix fenceinfo, string colvector dotags) { lce = 0 Y = _gr_preamble() for (i=1; i<=rows(X); i++) { //X[i,.] if (fenceinfo[i,2]==1) { Y = Y \ X[(lce+1)..i,.]\dotags[i,.] lce = i } else if (fenceinfo[i,2]==-1) { Y= Y \X[(lce+1)..(i-1),.]\dotags[i,.]\X[i,.]\_gr_link() lce = i } } return(Y) } string colvector function _inline_code(string colvector X) { for (i=1; i<=rows(X); i++) { dispdir = ustrregexm(X[i,1], "(`|~)\{?s(tata)?(.*)(`)") while (dispdir) { X[i,1] = ustrregexra(X[i,1], "(`|~)\{?s(tata)?", "<>") dispdir = ustrregexm(X[i,1], "(`|~)\{?s(tata)?(.*)(`)") } } return(X) } end