0

I'm using yasnippet to insert text into RMarkdown (.Rmd) files. For example, I can insert a code block which will produce a web map with something like this:

Snippet:

# -*- mode: snippet -*-
# name: web-map
# key: rmd-web-map
# expand-env: ((yas-after-exit-snippet-hook #'yas-web-map))
# --

\`\`\`{r echo = FALSE, eval = TRUE, message = FALSE, warning = FALSE}
library(leaflet)

loc <- c()

leaflet() %>%
    addTiles() %>%
    setView(lng = loc[2], lat = loc[1], zoom = 10)
\`\`\`

Contents of yas-web-map function:

  (defun yas-web-map ()
    "Insert web map used in xaringan presentations (meant to be
     called after pasting yas-snippet)"
    (search-backward "loc <- c()")
    (move-end-of-line nil)
    (forward-char -1)
    (if (y-or-n-p "Have coordinates from Google Maps?")
        (evil-paste-before 1)
      (evil-insert-state)))

This function, executed after the snippet is inserted into the buffer, conveniently asks if there are Google Maps coordinates copied to the clipboard; if so, they are pasted in so that they look something like this:

loc <- c(43.78122829024182, 11.302820020432307)

If coordinates aren't in the clipboard (user answers 'n'), the cursor is conveniently placed right after loc <- c( so that I can type them in manually.

While the boilerplate code in web-map snippet is useful the first time it's inserted, I often make small modifications to it and use this "updated" version as new boilerplate (by manually copying/pasting) and making further updates:

Original:

library(leaflet)

loc <- c()

leaflet() %>%
    addTiles() %>%
    setView(lng = loc[2], lat = loc[1], zoom = 10)

Updated boilerplate:

library(leaflet)

loc <- c(53.54002780542723, -113.49511179311895)

leaflet() %>%
    addProviderTiles(provider = providers$CartoDB.Positron) %>%
    setView(lng = loc[2], lat = loc[1], zoom = 8)

In future snippet insertions, instead of using the default web-map one, I'd like to first check if a modified one (like immediately above) exists first. If so, it should be inserted instead. This would be useful since I am often working in files hundreds of lines long, editing in various places within the file.

I've come up with a pure Emacs lisp solution using a combination of search-backward, evil-yank, etc., but this feels clunky and does not make use of snippets at all. What I'd really like is a snippet option that is the equivalent of # expand-env: ((yas-after-exit-snippet-hook #'yas-web-map)) but evaluates before the snippet is inserted. Does such a thing exist?

2
  • joaotavora.github.io/yasnippet/… ?
    – nega
    Nov 14, 2021 at 23:01
  • @nega Ahhh yeah I think that's it. I mulled this over a bit however, and I've wondering if yasnippet is overkill for what I want to do - since I only want to insert a defined text block and not make dynamic modifications, maybe something apart from yasnippet would be easier? Or maybe it would allow for further expansion and more customization in future to just use yasnippet.
    – haff
    Nov 16, 2021 at 0:17

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.