# publiccameronbracken/pgfSweave

### Subversion checkout URL

You can clone with HTTPS or Subversion.

# Bug fix in pgfSweave's handling of Sconcordance#32

Merged
merged 2 commits into from about 2 years ago
 +57 76

### 2 participants

commented June 16, 2011

Sweave keeps track of what lines in the weaved output correspond to what lines
in the source. This is useful for programs like the patchDVI R library, which
allow one to click on a spot in the compiled PDF file and be taken to the line
in the Rnw file which generated that portion of the PDF.

Previously, pgfSweave was mangling this info. This commit introduces a helper
function through which all code-chunk output should be passed. As a side
effect, it moves a lot of bolierplate into the helper function, cleaning up
the body of the pgfSweaveRunCode function.

 aecay Fix bookkeeping of output lines. Sweave keeps track of what lines in the weaved output correspond to what lines in the source. This is useful for programs like the patchDVI library, which allow one to click on a spot in the compiled PDF file and be taken to the line in the Rnw file which generated that portion of the PDF. Previously, pgfSweave was mangling this info. This commit introduces a helper function through which all code-chunk output should be passed. As a side effect, it moves a lot of bolierplate into the helper function, cleaning up the body of the pgfSweaveRunCode function. 2f90e0d
Owner

This is great! A much needed fix, I never use concordance so the suport for it was very haphazard, this is also a nice cleanup of the code. See my comment on the commit.

 aecay The stream is already open; reopening gives a warning. 02e1264
Owner

I think there is still one small bug when the tidy option is used with the keep.source option and a long code line or comment is wrapped. After running patchSynctex I get the warning:

Warning message:
In matrix(values[-1], nrow = 2) :
data length [33] is not a sub-multiple or multiple of the number of rows [2]


see: https://gist.github.com/1036173 for an example.

It doesn't seem to negatively affect the output but it is annoying.

Owner

Do you think you might fix this warning?

commented June 28, 2011

Sorry for the delayed response -- I've been on vacation and haven't had a chance to look in detail at what is going on in this case. The concordance is supposed to contain an odd number of numbers; superficially it looks like this case is causing an even number to be included. But whether this is a problem with pgfSweave, with patchDVI, or something inherited from base Sweave is not something I've been able to look at.

I'll be back from vacation on the 4th, so I hope to have a bugfix out within a few days of that time.

Owner

No worries, thanks again for your work!

commented July 25, 2011

OK, I've had a chance to look more at this problem, and figure out what is causing it. The warning message above is caused by the fact that the concordance (which is supposed to be a list of numbers) winds up containing NAs. This is what causes the parsing code in patchSynctex to barf.

It seems the NAs are caused by the keep.source option -- setting that to FALSE gives OK results for highlight=T. As far as I can see, this option only affects the behavior of the deparse(.tidy) call in pgfSweaveRuncode. I still haven't figured out how this percolates through the rest of the function to make NAs crop up. I'll keep trying to understand what goes on and update again when I have something more.

Owner

Cool, good to know, let me know if I can help at all.

referenced this pull request in yihui/knitr February 11, 2012
Open

### support concordance #133

merged commit 02e1264 into from March 19, 2012
closed this March 19, 2012

Showing 2 unique commits by 1 author.

Jun 16, 2011
Fix bookkeeping of output lines.
Sweave keeps track of what lines in the weaved output correspond to what lines
in the source.  This is useful for programs like the patchDVI library, which
allow one to click on a spot in the compiled PDF file and be taken to the line
in the Rnw file which generated that portion of the PDF.

Previously, pgfSweave was mangling this info.  This commit introduces a helper
function through which all code-chunk output should be passed.  As a side
effect, it moves a lot of bolierplate into the helper function, cleaning up
the body of the pgfSweaveRunCode function.
2f90e0d
Jun 19, 2011
The stream is already open; reopening gives a warning. 02e1264
 @@ -133,7 +133,7 @@ pgfSweaveWritedoc <- function(object, chunk) 133 133  if(length(which)){ 134 134  chunk[which] <- paste(chunk[which],"\\usetikzlibrary{external}", 135 135  "\\tikzexternalize[mode=list and make]\n", sep="\n") 136 - linesout <- linesout[c(1L:which, which, seq(from=which+1L, length.out=length(linesout)-which))] 136 + linesout <- linesout[c(1L:which, which, which, seq(from=which+1L, length.out=length(linesout)-which))] 137 137  object$havetikzexternalize <- TRUE 138 138  } 139 139  } @@ -159,12 +159,12 @@ pgfSweaveWritedoc <- function(object, chunk) 159 159  # put in the style definitions after the \documentclass command 160 160  if(length(which)) { 161 161  chunk <- c(chunk[1:which],hstyle,chunk[(which+1):length(chunk)]) 162 - linesout <- linesout[c(1L:which, which, seq(from = which + 162 + linesout <- linesout[c(1L:which, rep(which, length(hstyle)), seq(from = which + 163 163  1L, length.out = length(linesout) - which))] 164 164  object$haveHighlightSyntaxDef <- TRUE 165 165  } 166 166  } 167 -  167 + 168 168  while(length(pos <- grep(object$syntax$docexpr, chunk))) 169 169  { 170 170  cmdloc <- regexpr(object$syntax$docexpr, chunk[pos[1L]]) @@ -265,6 +265,20 @@ pgfSweaveRuncode <- function(object, chunk, options) { 265 265  } 266 266  else chunkout <- object$output 267 267   268 + write.chunk <- function(str, file = chunkout) { 269 + cat(str, file=file, append=TRUE) 270 + lo <- linesout 271 + tl <- thisline 272 + 273 + nlines <- sum(strsplit(str, NULL)[[1]] == "\n") 274 + 275 + if (nlines > 0) { 276 + lo[tl + 1:nlines] <- srcline 277 + assign("linesout", lo, parent.env(environment())) 278 + assign("thisline", tl + nlines, parent.env(environment())) 279 + } 280 + } 281 + 268 282  saveopts <- options(keep.source=options$keep.source) 269 283  on.exit(options(saveopts)) 270 284   @@ -357,12 +371,10 @@ pgfSweaveRuncode <- function(object, chunk, options) { 357 371  if(options$echo && length(dce)){ 358 372  if(!openSinput){ 359 373  if(!openSchunk){ 360 - cat("\\begin{Schunk}\n",file=chunkout, append=TRUE) 361 - linesout[thisline + 1] <- srcline 362 - thisline <- thisline + 1 374 + write.chunk("\\begin{Schunk}\n") 363 375  openSchunk <- TRUE 364 376  } 365 - cat("\\begin{", Sinputenv, "}", sep="", file=chunkout, append=TRUE) 377 + write.chunk(paste("\\begin{", Sinputenv, "}", sep="")) 366 378  openSinput <- TRUE 367 379  beginSinput <- TRUE 368 380  } @@ -374,35 +386,38 @@ pgfSweaveRuncode <- function(object, chunk, options) { 374 386  if(length(grep("^[[:space:]]*$",dce)) >= 1 & length(dce) == 1){ 375 387   376 388  # for blank lines for which parser throws an error 377 - cat(translator_latex(paste(getOption("prompt"),'\n', sep="")), 378 - file=chunkout, append=TRUE, sep="") 379 - cat(newline_latex(),file=chunkout, append=TRUE) 380 -  389 + write.chunk(translator_latex(paste(getOption("prompt"),'\n', sep=""))) 390 + write.chunk(newline_latex()) 381 391  }else{ 392 + if (!beginSinput) { 393 + write.chunk(newline_latex()) 394 + } 382 395   383 - if (!beginSinput) cat(newline_latex(), file=chunkout, append=TRUE) 396 + tmpcon <- file() 384 397   385 398  highlight(parser.output=parser(text=dce), 386 399  renderer=renderer_latex(document=FALSE), 387 - output = chunkout, showPrompts=TRUE,  400 + output = tmpcon, showPrompts=TRUE,  388 401  size=ifelse(is.null(getOption('highlight.size')), 389 402  "normalsize", getOption('highlight.size'))) 403 + cat("\n", file = tmpcon) # Just in case 404 + flush(tmpcon) 405 + write.chunk(readLines(tmpcon)) 406 + close(tmpcon) 390 407   391 408  } 392 409  beginSinput <- FALSE 393 410   394 411  }else{ 395 412  # regular output, may be tidy'd or not 396 - cat("\n",paste(getOption("prompt"), dce[1:leading], sep="", 397 - collapse="\n"), file=chunkout, append=TRUE, sep="") 398 - if (length(dce) > leading) 399 - cat("\n", paste(getOption("continue"), dce[-(1:leading)], sep="", 400 - collapse="\n"), file=chunkout, append=TRUE, sep="") 401 -  413 + write.chunk(paste("\n",paste(getOption("prompt"), dce[1:leading], sep="", 414 + collapse="\n"),sep="")) 415 + if (length(dce) > leading) { 416 + write.chunk(paste("\n", paste(getOption("continue"), dce[-(1:leading)], sep="", 417 + collapse="\n"), sep="")) 418 + } 402 419  } 403 420   404 - linesout[thisline + 1:length(dce)] <- srcline 405 - thisline <- thisline + length(dce) 406 421  } 407 422   408 423  # do not evaluate empty expressions, these may occur when tidy=T @@ -434,22 +449,16 @@ pgfSweaveRuncode <- function(object, chunk, options) { 434 449   435 450  if(length(output)>0 & (options$results != "hide")){ 436 451  if(openSinput){ 437 - cat("\n\\end{", Sinputenv, "}\n", sep="", file=chunkout, append=TRUE) 438 - linesout[thisline + 1:2] <- srcline 439 - thisline <- thisline + 2 452 + write.chunk(paste("\n\\end{", Sinputenv, "}\n", sep="")) 440 453  openSinput <- FALSE 441 454  } 442 455   443 456  if(options$results=="verbatim"){ 444 457  if(!openSchunk){ 445 - cat("\\begin{Schunk}\n",file=chunkout, append=TRUE) 446 - linesout[thisline + 1] <- srcline 447 - thisline <- thisline + 1 458 + write.chunk("\\begin{Schunk}\n") 448 459  openSchunk <- TRUE 449 460  } 450 - cat("\\begin{Soutput}\n",file=chunkout, append=TRUE) 451 - linesout[thisline + 1] <- srcline 452 - thisline <- thisline + 1 461 + write.chunk("\\begin{Soutput}\n") 453 462  } 454 463   455 464  output <- paste(output,collapse="\n") @@ -461,48 +470,33 @@ pgfSweaveRuncode <- function(object, chunk, options) { 461 470  output <- sub("\n[[:space:]]*\n", "\n", output) 462 471  } 463 472   464 - cat(output, file=chunkout, append=TRUE) 465 - count <- sum(strsplit(output, NULL)[[1]] == "\n") 466 - 467 - if (count > 0) { 468 - linesout[thisline + 1:count] <- srcline 469 - thisline <- thisline + count 470 - } 471 - 473 + write.chunk(output) 472 474  remove(output) 473 475   474 476  if(options$results=="verbatim"){ 475 - cat("\n\\end{Soutput}\n", file=chunkout, append=TRUE) 476 - linesout[thisline + 1:2] <- srcline 477 - thisline <- thisline + 2 477 + write.chunk("\n\\end{Soutput}\n") 478 478  } 479 479  } 480 480  } 481 481  } 482 482   483 483  if(openSinput){ 484 - cat("\n\\end{", Sinputenv, "}\n", sep="", file=chunkout, append=TRUE) 485 - linesout[thisline + 1:2] <- srcline 486 - thisline <- thisline + 2 484 + write.chunk(paste("\n\\end{", Sinputenv, "}\n", sep="")) 487 485  } 488 486   489 487  if(openSchunk){ 490 - cat("\\end{Schunk}\n", file=chunkout, append=TRUE) 491 - linesout[thisline + 1] <- srcline 492 - thisline <- thisline + 1 488 + write.chunk("\\end{Schunk}\n") 493 489  } 494 490   495 491  if(is.null(options$label) & options$split) 496 492  close(chunkout) 497 493   498 494  if(options$split & options$include){ 499 - cat("\\input{", chunkprefix, "}\n", sep="", 500 - file=object$output, append=TRUE) 501 - linesout[thisline + 1] <- srcline 502 - thisline <- thisline + 1 495 + write.chunk(paste("\\input{", chunkprefix, "}\n", sep=""), 496 + file=object$output) 503 497  } 504 498   505 - if(options$fig && options$eval){ 499 + if(options$fig && options$eval) { 506 500   507 501  chunkChanged <-  508 502  if( options$external ) @@ -617,47 +611,34 @@ pgfSweaveRuncode <- function(object, chunk, options) { 617 611   618 612  # Write the extrnalization commands 619 613  if(options$include && options$external) { 620 - cat("\n\\tikzsetnextfilename{",chunkprefix,"}\n",sep="", 621 - file=object$output, append=TRUE) 622 - cat("\n\\tikzexternalfiledependsonfile{",chunkprefix,"}{", 623 - paste(chunkprefix, "tikz", sep="."),"}\n",sep="", 624 - file=object$output, append=TRUE) 614 + write.chunk(paste("\n\\tikzsetnextfilename{",chunkprefix,"}\n",sep=""), 615 + file=object$output) 616 + write.chunk(paste("\n\\tikzexternalfiledependsonfile{",chunkprefix,"}{", 617 + paste(chunkprefix, "tikz", sep="."),"}\n",sep=""), 618 + file=object$output) 625 619   626 - linesout[thisline + 1] <- srcline 627 - thisline <- thisline + 1 628 -  629 620  } 630 621   631 622  # Write the includegraphics command for eps or pdf  632 623  # only if we are not useing pgf or tikz 633 624  if(options$include && !options$pgf && !options$tikz && !options$external) { 634 625   635 - cat("\\includegraphics{", chunkprefix, "}\n", sep="", 636 - file=object$output, append=TRUE) 637 - linesout[thisline + 1] <- srcline 638 - thisline <- thisline + 1 639 - 626 + write.chunk(paste("\\includegraphics{", chunkprefix, "}\n", sep=""), 627 + file=object$output) 640 628  } 641 629  # input statements for tikz and pgf 642 630  if(options$include && (options$pgf || options$tikz)) { 643 - 644 631  #if tikz takes precident over pgf option 645 632  suffix <- ifelse(options$tikz,'tikz','pgf') 646 633  if(!options$external){ 647 - cat("{\\tikzexternaldisable\n", sep="", file=object$output, append=TRUE) 648 - linesout[thisline + 1] <- srcline 649 - thisline <- thisline + 1 634 + write.chunk("{\\tikzexternaldisable\n", file=object$output) 650 635  } 651 636   652 - cat("\\input{", paste(chunkprefix,suffix,sep='.'), 653 - "}\n", sep="", file=object$output, append=TRUE) 654 - linesout[thisline + 1] <- srcline 655 - thisline <- thisline + 1 637 + write.chunk(paste("\\input{", paste(chunkprefix,suffix,sep='.'), 638 + "}\n", sep=""), file=object$output) 656 639   657 640  if(!options$external){ 658 - cat("}\n", sep="", file=object$output, append=TRUE) 659 - linesout[thisline + 1] <- srcline 660 - thisline <- thisline + 1 641 + write.chunk("}\n", file=object$output) 661 642  } 662 643   663 644  }