Skip to content

Add pkg_detail RPC for packages pane detail editor#1291

Open
bricestacey wants to merge 6 commits into
mainfrom
12926/package-detail-rpc
Open

Add pkg_detail RPC for packages pane detail editor#1291
bricestacey wants to merge 6 commits into
mainfrom
12926/package-detail-rpc

Conversation

@bricestacey

@bricestacey bricestacey commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Adds a .ps.rpc.pkg_detail(name) RPC that returns cheap, kernel-local detail
metadata for a single installed package. Positron's new package detail editor
calls this when a package is opened.

The RPC reads the installed package's DESCRIPTION via
utils::packageDescription(...) and returns a named list with:

  • name
  • dependencyCount - count of Depends + Imports + LinkingTo, excluding
    base packages and R itself
  • title - the Title field (when present)
  • author - Maintainer, falling back to Author (when present)
  • license - the License field (when present)
  • sourceRepository - the Repository field, e.g. "CRAN" (when present)
  • publishedDate - the Date/Publication field (when present)

It returns NULL for an empty name or a package that isn't installed. No Rust
change is needed - the generic .ps.rpc.<method> dispatch in
crates/ark/src/ui/ui_comm.rs already routes it.

Companion Positron work: posit-dev/positron#12926 (the package detail
editor, which adds the getPackageDetail package-manager hook that calls this
RPC). The Positron PR will bump the ark submodule to this change once merged.

Positron PR: posit-dev/positron#14440

QA

In an R session:

positron:::.ps.rpc.pkg_detail("utils")   # base pkg: name/title/author/license, dependencyCount 0
positron:::.ps.rpc.pkg_detail("dplyr")   # CRAN pkg: + sourceRepository, publishedDate, dependencyCount > 0
positron:::.ps.rpc.pkg_detail("nope")    # NULL

(Exact accessor depends on how the module is exposed; the function is
.ps.rpc.pkg_detail in crates/ark/src/modules/positron/packages_pane.R.)

@jennybc jennybc left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I made a few inline suggestions.

I know this PR is not really about the shape and look of the package detail editor. But I'll go ahead and mention that I'd probably include some things that aren't here (e.g. link to package's main site, if available, or its CRAN landing page) and omit or refactor some things that are here (e.g. dependency count seems less useful than just revealing those DESCRIPTION fields or giving the typical dependency/reverse dependency treatment seen on CRAN and METACRAN).

Comment on lines +121 to +124
installed <- rownames(utils::installed.packages())
if (!nzchar(name) || !(name %in% installed)) {
return(NULL)
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It will be more efficient to just go directly to utils::packageDescription(), which will return NA if the package is not installed. This avoids reading and parsing DESCRIPTION of all installed packages for this existence check. installed.packages() docs say:

It will be slow when thousands of packages are installed, so do not use it to find out if a named package is installed (use find.package or system.file) nor to find out if a package is usable (call requireNamespace or require and check the return value) nor to find details of a small number of packages (use packageDescription).

first
}

base_pkgs <- rownames(utils::installed.packages(priority = "base"))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Given the downsides to calling installed.packages() when it can be avoided, I would just hardwire these. They don't change. I have a history of doing same:

https://github.com/r-lib/usethis/blob/bd15dceaf98338b6758becc38193fdaff2d9776a/R/tidyverse.R#L363-L403

If you really want to compute it, I'd suggest:

tools:::.get_standard_package_names()$base

out <- list(name = name, dependencyCount = length(deps))

# Prefer Maintainer for author display; fall back to Author.
author <- clean(d$Maintainer)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

FWIW a CRAN package absolutely must have a Maintainer. But I suppose this pane could populate from a non-CRAN source? Just thought I'd mention.

Comment on lines +196 to +209
if (!is.null(title)) {
out$title <- title
}
if (!is.null(author)) {
out$author <- author
}
if (!is.null(license)) {
out$license <- license
}
if (!is.null(repo)) {
out$sourceRepository <- repo
}
if (!is.null(published)) {
out$publishedDate <- published

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If you definitely want to drop the NULLs (I guess that's favorable on the other side?), something along these lines might be more readable:

out <- list(
    name = name,
    title = title,
    author = author,
    license = license,
    sourceRepository = repo,
    publishedDate = published
)
Filter(Negate(is.null), out)

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.

2 participants