r-lib / diffviewer

HTML widget to visually compare files
http://diffviewer.r-lib.org
Other
58 stars 7 forks source link

Add basic vignette #4

Open hadley opened 4 years ago

hadley commented 4 years ago

Using selection of examples from http://rpubs.com/jbkunst/diffviewer

olivroy commented 3 months ago

When you are working on this again, I'd like to suggest to add an example of how you can wrap git + diffviewer to view your uncommited changes without having to go to the RStudio git pane.

view_change_between_current_and_uncommited_file <- function(uncommited_file, repo = ".") {
  uncommited_file
  uncommited_file <- fs::path_rel(
    fs::path_real(uncommited_file),
    fs::path_real(repo)
  )
  if (repo != ".") {
    # change dir temporarily
    withr::with_dir(repo, {
      old_file_lines <- system(paste("git show HEAD:", uncommited_file), intern = TRUE)
    })
  } else {
    old_file_lines <- system(paste0("git show HEAD:", uncommited_file, "\""), intern = TRUE)
  }

  tmp_dir <- withr::local_tempdir()
  file_old <- fs::path(tmp_dir, paste0(fs::path_ext_remove(fs::path_file(uncommited_file)), "-uncommited"), ext = fs::path_ext(uncommited_file))
  xfun::write_utf8(
    con = file_old,
    text = old_file_lines
  )
  diffviewer::visual_diff(
    file_old = file_old,
    file_new = uncommited_file,
    height = 100
  )
}
view_change_between_current_and_uncommited_file("DESCRIPTION")

image

My "final" version looks more like this. To allow showcasing never commited files too + allow to call without argument and defaulting on the currently open document.


  visual_diff <- function(uncommited_file = reuseme::active_rs_doc(), repo = ".") {
    rlang::check_installed(c("diffviewer", "gert", "xfun", "fs"))
    if (is.null(uncommited_file)) {
      cli::cli_abort("Not for unsaved documents.")
    }
    uncommited_file <- fs::path_rel(
      fs::path_real(uncommited_file),
      fs::path_real(repo)
    )
    if (stringr::str_detect(uncommited_file, "\\.\\./")) {
      cli::cli_abort("uncommited file can't be outside repo.")
    }
    if (!fs::is_file(uncommited_file)) {
      cli::cli_abort("{.arg uncommited file} must be an existing file.")
    }
    if (is.na(gert::git_stat_files(uncommited_file)$modified)) {
      # Solution
      cli::cli_inform("New (uncommited) file {.run [Click to delete])(fs::file_delete({as.character(uncommited_file)}))}.")
      tmp_dir <- withr::local_tempdir()
      empty_file <- fs::path(tmp_dir, uncommited_file)
      xfun::write_utf8(
        text = "",
        empty_file
      )
      return(diffviewer::visual_diff(
        file_old = empty_file,
        file_new = uncommited_file,
        height = 100
      ))
    }
    if (repo != ".") {
      # change dir temporarily
      withr::with_dir(repo, {
        old_file_lines <- system(paste("git show HEAD:", uncommited_file), intern = TRUE)
      })
    } else {
      old_file_lines <- system(paste0("git show HEAD:", uncommited_file, ""), intern = TRUE)
    }

    tmp_dir <- withr::local_tempdir()
    file_old <- fs::path(tmp_dir, paste0(fs::path_ext_remove(fs::path_file(uncommited_file)), "-uncommited"), ext = fs::path_ext(uncommited_file))
    xfun::write_utf8(
      con = file_old,
      text = old_file_lines
    )
    diffviewer::visual_diff(
      file_old = file_old,
      file_new = uncommited_file,
      height = 100
    )

I ended up not finding this very useful in practice because it doesn't resolve line copying problem (copying in the widget copies the line number, which is what I wanted to avoid with the git pane)

I use a function based on cli links that allows to easily copy content, and also navigate to the correct place (with cli links).