-
-
Notifications
You must be signed in to change notification settings - Fork 51
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added an option to tidy_source() to enforce a strict maximum line length. #71
Conversation
… with other functions.
…OL COMBINING SPRECHGESANG STEM character) to save space.
The behaviour with inline comments is now a little better. Unfortunately, if I've tried changing that code, but it doesn't work very well in |
Much appreciated! I'll review this tomorrow. |
I did a simpler (and less efficient) hack to It works for the pdf book I'm writing in most of the cases. I don't know if this approach may conflict with other use-cases. PS: bookdown + formatR are awesome!
|
Just FYI, I submitted an Enhancement request to implement this at the |
The R Bugzilla (https://bugs.r-project.org/bugzilla/show_bug.cgi?id=17390) request was closed, though they are open to the possibility of a patch. |
@yihui , what about using |
For the record: styler (as of version 1.0.2) does not currently support line width enforcement, but there is WIP to achieve this (contributed by @krivit, will be finalized by @lorenzwalthert), see r-lib/styler#414. |
Conflicts: DESCRIPTION R/tidy.R man/tidy_source.Rd
…ter may not work on Windows
…y search for the optimal width fails
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@krivit I made a couple of changes in your PR:
-
Instead of introducing a new
width.strict
argument, I'm treatingI(width)
as the maximum width. This saves one argument, but I'm open to adding a new argument if you don't like theI()
dea. -
The binary search is actually a little tricky here, because the deparsed line width is not a monotonic function of the specified width. Sometimes the deparsed width can decrease as the desired width increases, e.g.,
f = function(text, width) { unlist(lapply(width, function(w) { max(nchar(deparse(parse(text = text, keep.source = FALSE)[[1]], width.cutoff = w))) })) } x = paste(c(rep('1', 20), '1234567890'), collapse = '+') i = 20:100 plot(i, f(x, i), type = 'b', pch = 20)
So when the binary search fails, I use the brute-force to try all the rest of possible widths.
Please let me know if you have any feedback. I'm going to merge this PR for now, but open to suggestions as I said earlier. Thanks a lot!
#' | ||
#' If the value of the argument \code{width.cutoff} is wrapped in | ||
#' \code{\link{I}()} (e.g., \code{I(60)}), it will be treated as the \emph{upper | ||
#' bound} on the line width, but this upper bound may not be satisfied. In this | ||
#' case, the function will perform a binary search for a width value that can | ||
#' make \code{deparse()} return code with line width smaller than or equal to | ||
#' the \code{width.cutoff} value. If the search fails to find such a value, it | ||
#' will emit a warning, which can be suppressed by the global option | ||
#' \code{options(formatR.width.warning = FALSE)}. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for merging this PR! It will be great to have this Just Work.
I think this paragraph isn't 100% clear, because it can be read as the upper bound potentially not being satisfied after I()
is used. Suggested edit:
#' If the value of the argument \code{width.cutoff} is wrapped in
#' \code{\link{I}()} (e.g., \code{I(60)}), it will be treated as the
#' \emph{upper bound} on the line width. The corresponding argument to
#' \code{deparse()} is actually a lower bound, and so the function
#' will perform a binary search for a width value that can make
#' \code{deparse()} return code with line width smaller than or equal
#' to the \code{width.cutoff} value. If the search fails to find such
#' a value, it will emit a warning, which can be suppressed by
#' the global option \code{options(formatR.width.warning = FALSE)}.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the suggestion! I'll commit that later.
This patch adds another option,
width.strict=
totidy_source()
, defaulting toFALSE
. IfTRUE
, instead of callingdeparse()
withwidth.cutoff=
directly, it calls a new function,strict_deparse(..., width.max)
, which performs a binary search for the highestwidth.cutoff=
value to pass todeparse()
such that the longest line in its output is, after stripping trailing whitespace, at mostwidth.max=
in length.It seems to work quite well in most situations, though it still doesn't handle inline comments very well: the magic constant
%InLiNe_IdEnTiFiEr%
counts towards the line length, though it shouldn't. A possible solution might be to replace this magic constant with something much shorter, perhaps involving non-ASCII characters (which are legal in variable names in R, as far as I know) to reduce chances of a collision.