not-package/extras/patchKnitrSynctex.R

# patchSynctex(texfile) - for texfile="blubb.tex" it does use the "blubb-concordance.tex" 
#  file generated by knitr to patch the blubb.synctex[.gz] file generated by latex in order to
#  fix forward and reverse seach between blubb.pdf and blubb.Rnw
#
# tested only under windows, with one single utf8 Rnw file.
#
# Author: Jan Gleixner <jan.gleixner@gmail>
###############################################################################

patchKnitrSynctex <- function (texfile){
	require(tools)
	f=paste0(tools::file_path_sans_ext(texfile), "-concordance.tex")
	if (!file.exists(f)) 
		stop(paste(f,"does not exist! Did you set 'opts_knit$set(concordance = TRUE);'?"))
	text<-readChar(f, file.info(f)$size);
	require(stringr)
	re="\\\\Sconcordance\\{concordance:([^:]*):([^\\%]*):\\%\\r?\\n(\\d+)(( \\d+ \\d+)*)\\}";
	parsed=str_match_all(text,re);
	for(i in seq(1,nrow(parsed[[1]]))){		
		texF=parsed[[1]][i,2];
		rnwF=parsed[[1]][i,3];
		startLine=as.integer(parsed[[1]][i,4]);
		rleValues <- read.table(textConnection(parsed[[1]][i,5]));
		rleO = rle(0);
		rleO$values=as.numeric(rleValues[seq(2,length(rleValues),2)]);
		rleO$lengths=as.integer(rleValues[seq(1,length(rleValues),2)]);
		diffs=inverse.rle(rleO);
		mapping_=c(startLine,startLine+cumsum(diffs[-1]));
		
		basename <- tools::file_path_sans_ext(rnwF);		
		syncF = paste0(basename,".synctex");
		
		compressed <- FALSE
		if (file.exists(syncF)) {
			sf=file(syncF);
		} else{
			syncF <- paste(syncF, ".gz", sep = "")
			if (file.exists(syncF)) {
				compressed <- TRUE
				sf <- gzfile(syncF);
			}
		}
		lines <- try(readLines(syncF, warn = FALSE), silent = TRUE)
		if (inherits(lines, "try-error")) 
			stop(paste(f, "cannot be read, no patching done."))
		close(sf)
		postemble =grep("^Postamble:",lines,perl=T)
		re=paste0("^Input:([^:]+):(.*", basename(texF), ")");		
		toRepl=grep(re,lines[seq(1,postemble)],perl=T);
		inputs=str_match(lines[toRepl],re);
		if (length(inputs)>0){
			tag=inputs[,2];
			inputs[,3]=paste0(tools::file_path_sans_ext(inputs[,3]), ".Rnw");
			lines[toRepl]=paste0("Input:",inputs[,2],":",inputs[,3]);
			re=paste0("^([xkgvh\\$\\(\\[]", tag ,"\\,)(\\d+)([\\,:].*)");
			needReplacment=grep(re,lines[seq(1,postemble)],perl=T);
			toRepl=str_match(lines[needReplacment],re);
			toRepl[,3]=as.character(mapping_[as.integer(toRepl[,3])]);
			newlines=paste0(toRepl[,2],toRepl[,3],toRepl[,4]);
			lines[needReplacment]=newlines;
			if (!compressed) {
				sf=file(syncF,"wb");
			} else{
				sf <- gzfile(syncF,"wb");
			}
			writeLines(lines, sf, sep = "\n")
			close(sf);
			print(paste(length(needReplacment), "patches made to",syncF));
		}else{
			print(paste("No patches made to",syncF));
		}
	}
}
eriqande/SNPcontam documentation built on May 16, 2019, 8:44 a.m.