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

Add use_air() #2109

Merged
merged 16 commits into from
Mar 5, 2025
Merged

Add use_air() #2109

merged 16 commits into from
Mar 5, 2025

Conversation

DavisVaughan
Copy link
Member

@DavisVaughan DavisVaughan commented Mar 3, 2025

For posit-dev/air#224

Note that while use_tidy_style() actually invokes styler, use_air() is just about getting your project set up to use Air. The documentation states everything that this does so I won't repeat here.

I can't use jsonlite::write_json() directly due to some fiddly details I documented and talked to @jeroen about, so we have a small shim that mimics it for use with VS Code settings json files.

I've tried to structure these functions with potential future use in mind.

I would not be surprised if writing JSON back to file doesn't result in a perfect roundtrip in terms of formatting, but I think that should be okay, especially if people use version control.

@hadley
Copy link
Member

hadley commented Mar 3, 2025

Should this also run air on the whole project?

@DavisVaughan
Copy link
Member Author

Should this also run air on the whole project?

With use_air(), I'm mostly interested in helping people get set up to Format On Save in Positron using recommended best practices (settings.json at the workspace level so its shared among contributors, extensions.json that prompts contributors to install the extension, etc). It does also make air.toml and add to .Rbuildignore, which is also helpful in RStudio.

I think this function is more in line with other one-time-setup helpers than with use_tidy_style() which tries to invoke styler.


The current initial workflow for Air in Positron for an existing project looks like:

  • Install Air CLI
  • Install Air OpenVSX Extension
  • usethis::use_air()
  • Commit
  • air format . one time using the Air CLI to get the whole project in order
  • Commit
  • Switch to Format on Save using the Air Extension from here on out

The current initial workflow for Air in RStudio for an existing project looks like:

  • Install Air CLI
  • usethis::use_air()
  • Commit
  • air format . one time using the Air CLI to get the whole project in order
  • Commit
  • Switch to Format on Save using Air as an "external formatter" from here on out

I don't think we can improve on RStudio any further unless it bundles Air. But with VS Code / Positron I'd like to remove the CLI from the picture so it looks like:

  • Install Air OpenVSX Extension
  • usethis::use_air()
  • Commit
  • Run Air: Format project using the Air Extension
  • Commit
  • Switch to Format on Save using the Air Extension from here on out

I don't think having use_air() try and invoke Air will be super helpful here, as it will have a pre-req that Air is installed as a command line tool, and in our ideal world that actually won't be the case for Positron users (it'll be bundled in the extension but not available at the command line unless they install it themselves)

@hadley
Copy link
Member

hadley commented Mar 3, 2025

Ok, in that case, I'd recommend that you describe that in the docs. Or maybe include a todo bullet to remind the user to also run air format themselves.

Copy link
Member

@jennybc jennybc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will be cool! I made a few comments, many of which surface existing patterns in usethis that could be used here.

R/air.R Outdated
#' `.vscode/extensions.json`. This includes:
#'
#' - Setting `editor.formatOnSave = true` for R files to enable formatting on
#' every save. Does nothing if `editor.formatOnSave` was already set.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is something of an existing convention where we use can_overwrite() to determine if it's safe to err on the side of making change in a file. If the user has set the usethis.overwrite option to TRUE and we're making changes inside a project that is a Git repo, we just go ahead and do it. I have this set to TRUE in my .Rprofile.

I'm not sure if you'd like to do that here, but just wanted you to know about this pattern.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'd use that if we were completely overwriting. In this particular case, we want to merge with what the user already has as much as possible, so I think not asking or checking is ok in this case.

I do think I'm going to remove this though

Does nothing if `editor.formatOnSave` was already set.
Does nothing if `editor.defaultFormatter` was already set.

I think we actually should update this, as you've explicitly requested Air with use_air(), so you've opted into these recommended settings already

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah when I first looked at this I thought maybe it was overly cautious / overly respectful of existing settings. Happy to have it just make these changes unconditionally.

@DavisVaughan
Copy link
Member Author

Added a note in the docs about how this does not actually invoke Air, and added this TODO bullet at the end

Screenshot 2025-03-04 at 11 07 06 AM

@jennybc
Copy link
Member

jennybc commented Mar 4, 2025

The CI failures seem to be related to bad weather at httpbin.org and not related to the content of this PR.

@DavisVaughan DavisVaughan merged commit a653d6e into main Mar 5, 2025
26 of 32 checks passed
@DavisVaughan DavisVaughan deleted the feature/air branch March 5, 2025 13:25
}

write_air_vscode_extensions_json <- function(path) {
settings <- jsonlite::read_json(path)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this operation may fail because settings.json is actually JSONC (JSON with Comments), not JSON.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. Darn! jeroen/jsonlite#394

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

Successfully merging this pull request may close these issues.

6 participants