Skip to content
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

Enforcing a 80-character line length rule? #247

Open
jarodmeng opened this issue Oct 22, 2017 · 30 comments
Open

Enforcing a 80-character line length rule? #247

jarodmeng opened this issue Oct 22, 2017 · 30 comments

Comments

@jarodmeng
Copy link

Is it possible to enforce a rule to limit code to 80 character per line? styler currently doesn't seem to do that. The closest issue I can find is #118, but it's not clear if that option is available.

@lorenzwalthert
Copy link
Collaborator

lorenzwalthert commented Oct 22, 2017

Thanks for having consulted open issues first. #118 is an edge case as far as indention goes and not quite what you are referring to. The task of splitting lines of code with more than 80 characters is non-trivial as it is not a-priori clear at which position lines should be split. I think this may also not follow a general and abstract rule (as the other styling rules) but is best done manually and decided on a case-to-case basis. Therefore, this feature is currently no supported in styler and will probably no be so in the near future. We suggest to use the packages lintr to detect lines with more than 80 characters and rearrange manually.

Edit: I think we aim to support this in the long run.

@krlmlr
Copy link
Member

krlmlr commented Oct 23, 2017

I'm working on (finally!) releasing utf8, this means we could release styler soon. After this I think we could start thinking about that 80-character rule, because editing code from "wide" to "long" takes quite a lot of time (measured in seconds, but still). I'd like to suggest to do it at the level of function calls and arithmetic expressions first:

  • If a single-line function call hits the 80-character boundary, add a line break after the opening paren, and proceed with usual rules.
  • If an arithmetic expression is too wide, add line breaks after lowest-prio operators (i.e., the + in 1 * 2 + 3 * 4)

Maybe start with only function calls -- if we add a set of rules after all other rules (because we need to be sure about the width), and then do only reindention of function call arguments?

@jarodmeng
Copy link
Author

Thanks for the reply! I agree that it's not easy to implement such a rule. @krlmlr 's suggestion looks good to me.

@lorenzwalthert
Copy link
Collaborator

So do you @krlmlr suggest to take the 80 character limit from the (raw) unstyled expression, right?

@krlmlr
Copy link
Member

krlmlr commented Oct 24, 2017

No, that would be after styling, when we know the final width -- we'd just add linebreaks but not change much otherwise.

@lorenzwalthert
Copy link
Collaborator

Issues that can't be resolved soonish will be closed and labelled "Status: Postponed".

@lorenzwalthert
Copy link
Collaborator

Reference: #65.

@krivit
Copy link

krivit commented Apr 9, 2018

@lorenzwalthert , I've implemented a version of this, by adding a loop to parse_transform_serialize to do the following:

  1. Run through the formatting and flattening process to obtain flattened_pd.
  2. See if any of the tokens have an end column greater than the limit. If any do, note the first token with this property and add its pos_id to a list. If none do, render the text and exit.
  3. Prepend a formatter (I call it add_line_break_at_pos_id constructed by mk_add_line_break_at_pos_id) to the line_break formatters. This formatter increments lag_newlines for the elements which either have one of the stored pos_ids or have a child that does.
  4. Repeat from Step 1 with the additional formatter, until exit.

I've committed the implementation to a fork (4017b39). It's not pull-request-ready, and I would appreciate your input as to whether it's worth developing into something that is.

@lorenzwalthert
Copy link
Collaborator

lorenzwalthert commented Apr 10, 2018

Thanks @krivit for looking into it. To be honest, I first need to think about what I had in mind earlier this year about implementing that feature. I think there were some obstacles I can't quite remember as I was reflecting on different approaches. As it looks to me, your approach seems to work (maybe need to handle cases where indention >= 80 so line break won't help at all and we will be stuck in infinite loop) but I am not sure if there is a better way of doing it. Anyways, I first have to fully understand what you do and maybe also giving it a fresh try myself - at least conceptually, so we can figure out the best way of implementing that feature. As soon as we have reached a high-level consensus about how to go about it, I think we can start moving your branch towards that if you are willing to.

I could give you some feedback on your code right away but I think I first want to think about the larger picture before we optimise the details.

Also, I would like to only implement line breaks for function calls first as @krlmlr suggested in his comment.

Is that ok for you?

@krivit
Copy link

krivit commented Apr 10, 2018

Thanks for reopening the issue. The plan sounds fine. The way I see it, any implementation will be inherently inelegant, for two reasons:

  • Every line break inserted will change how the rest of that line is indented.
  • Inserting a line break can turn a one-line expression into a multiline expression, which follows different rules.

So, any algorithm will be some form of trial-and-error.

Here are some additional issues I can think of, in addition to those you had mentioned:

  • It grabs the maximum width from getOption("width"), but is that what we want?
  • I haven't tested it, but I'm pretty sure that it's willing to break a line before a comma. This could be handled by listing the types of tokens that should not have a break before them, and breaking before the token before them.
  • It can't insert line breaks within a comment or a string literal. This means that a comment or a string that's too long is going to cause an infinite loop as well. That said, this can be addressed simply by not counting any token that is immediately preceded by a line break as "overflowing".
  • Changing a call from single-line to multiline changes the indentation preceding the overflowing token, which may change which token would have overflowed.

@lorenzwalthert
Copy link
Collaborator

@krivit can you open a PR anyways already with the WIP so we don't forget about it?

@krivit
Copy link

krivit commented Apr 24, 2018

@lorenzwalthert, done.

lcolladotor added a commit to lcolladotor/BiocCheck that referenced this issue May 19, 2020
This commit resolves Bioconductor#57
by updating the `handleMessage()` calls after the formatting check
fails. Instead of mentioning `formatR`, these messages now refer to:

* `styler`,
* `biocthis`,
* the `BiocCheck` vignette.

Furthermore, the `BiocCheck` vignette section on formatting still
mentions `formatR`, but it now also mentions in more detail:

* `styler`: how to install and run it
* `biocthis`: as a companion to `styler` with code how to run it
(but not install it since it's optional and the install instructions
will hopefully change soon once this package is submitted/reviewed).
* a quick overview of the differences between `formatR` and `styler`,
though this is mostly done by highlighting current limitations of
`formatR`.
* how RStudio Desktop's `Reformat code` button (under the magic wand)
can help break long lines which is something that `styler` cannot do
as discussed in more detail at
r-lib/styler#247. `formatR` can do this,
but personally, the fact that it broke valid R code in some of my
packages made me trust its output less.

The NEWS and DESCRIPTION files have been updated accordingly.
@RobertMyles
Copy link

Hi folks, just wondering what the status is on this issue? It would be a helpful addition :-)

Thanks.

@lorenzwalthert
Copy link
Collaborator

I am not currently working on that. We first need to outline conceptually what the implementation (or a first version) will look like. I think what I outlined in #247 (comment) is a good start.

@RobertMyles
Copy link

Ok, thanks!

@lorenzwalthert
Copy link
Collaborator

lorenzwalthert commented Jun 30, 2020

But I admit, the growing number of 👍 in the issue is motivating 😄

psychelzh added a commit to psychelzh/tarflow.iquizoo that referenced this issue Apr 13, 2021
Change global and targets to `character`, see r-lib/styler#247, it is rather hard to to styling for long lines.

Signed-off-by: Liang Zhang <psychelzh@outlook.com>
@euklid321
Copy link

Hi guys, one year after the last question... 😉 is there any chance that this would be implemented in the near future? I've been using styler quite actively for a couple of months now and I think this is the only major missing piece.

@lorenzwalthert
Copy link
Collaborator

lorenzwalthert commented Sep 11, 2021

I know this is high up on the wish list for many users but I anticipate this to be quite complex and time consuming to implement. Given other priorities in my life as well as in {styler}, I won't build this soon unfortunately. I hope you can understand this.

@moritzpschwarz
Copy link

For knitting PDF documents Carlos Luis Rivera posted a very useful answer on my StackOverflow post, which might be helpful for some people. It requires including the following to your header:

---
title: "R Notebook"
output: pdf_document
header-includes:
  - |
    ```{=latex}
    \usepackage{fvextra}
    \DefineVerbatimEnvironment{Highlighting}{Verbatim}{
      breaksymbolleft={}, 
      showspaces = false,
      showtabs = false,
      breaklines,
      commandchars=\\\{\}
    }
    ```
---

```{r}
knitr::opts_chunk$set(tidy="styler")
```

LiNk-NY pushed a commit to Bioconductor/BiocCheck that referenced this issue Aug 24, 2023
This commit resolves #57
by updating the `handleMessage()` calls after the formatting check
fails. Instead of mentioning `formatR`, these messages now refer to:

* `styler`,
* `biocthis`,
* the `BiocCheck` vignette.

Furthermore, the `BiocCheck` vignette section on formatting still
mentions `formatR`, but it now also mentions in more detail:

* `styler`: how to install and run it
* `biocthis`: as a companion to `styler` with code how to run it
(but not install it since it's optional and the install instructions
will hopefully change soon once this package is submitted/reviewed).
* a quick overview of the differences between `formatR` and `styler`,
though this is mostly done by highlighting current limitations of
`formatR`.
* how RStudio Desktop's `Reformat code` button (under the magic wand)
can help break long lines which is something that `styler` cannot do
as discussed in more detail at
r-lib/styler#247. `formatR` can do this,
but personally, the fact that it broke valid R code in some of my
packages made me trust its output less.

The NEWS and DESCRIPTION files have been updated accordingly.


Former-commit-id: 5604071
@ssh352
Copy link

ssh352 commented Jan 15, 2024

I use styler to format R code. Lintr gives me warning on lines on 80 characters line limit. However it seems styler has no option to specify max number of characters per line. I'd rather enforce the line width automatically instead of manually. How do R users enforce line width limit in Rstudio or in vim?

❯ Rscript -e "styler::style_file(commandArgs(trailingOnly = TRUE),indent_by=4)" script.R

@maikol-solis
Copy link

Hi everyone, I opened the issue #1192, and I just realized it's a duplicate of this.

Should I close my issue, or not?

Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests