1

So, I have a function that sends a URL to bit.ly for shortening and returns the short URL, and a (replace-regexp-in-string), which is supposed to grab the URL out of a string to passes it to that function.

Funny thing is -- both of these work fine on their own, but when I combine them, I end up with a mess.

(defun crshd/shorten-url (url)
  (let* ((bitly-url (format "https://api-ssl.bit.ly/v3/shorten?access_token=%s&format=%s&longUrl=%s"
                            crshd--bitly-api-key
                            "txt"
                            url))
         (response-buffer (url-retrieve-synchronously bitly-url)))
    (with-current-buffer response-buffer
                (buffer-substring (+ url-http-end-of-headers 1) (- (point-max) 1)))))

(replace-regexp-in-string "http.?://[a-z0-9./?&%#-_=]+"
                          'crshd/shorten-url
                          "replace http://emacs.stackexchange.com in this string"
                          nil nil)

And I end up with "replace http://emachttp://bit.ly/2a1zTGW.stackexchange.com in this string"

At the same time, (crshd/shorten-url "http://emacs.stackexchange.com") returns "http://bit.ly/2a1zTGW", as expected.

(defun crshd/foo-url (url)
  "foo")

(replace-regexp-in-string "http.?://[a-z0-9./?&%#-_=]+"
                          'crshd/foo-url
                          "replace http://emacs.stackexchange.com in this string"
                          nil nil)

Also returns "replace foo in this string".

What am I missing here?

  • 2
    Maybe it is because the function from url.el is modifying the Match Data within replace-regexp-in-string, if so, you can use save-match-data to keep the Match Data unchaged after calling crshd/shorten-url. – xuchunyang Jul 28 '16 at 9:39
  • Tangentially, did you mean to include the range #-_ in your character alternative? I haven't checked what that would be, but it looks like a mistake. – phils Jul 28 '16 at 9:45
  • @xuchunyang That was it. Should be an answer, so I can accept it :P – crshd Jul 28 '16 at 11:58
2

Emacs search functions (such as re-search-forward, replace-regexp-in-string etc) store the search result as the Match data. The later search overwrites the previous search's Match data by default. If you have to do another search within one search, you need to save & restore the Match data before/after the inner search, Emacs provides save-match-data for this purpose.

(replace-regexp-in-string some-regexp
                          (lambda (_match)
                            (save-match-data

                              do-another-search

                              ))
                          some-string)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.