Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you write an emacs lisp function to replace a word at point?

Tags:

emacs

elisp

I have tried in two different ways to write my function. I decided to write a small function to convert to camel case and back with this elisp string library. At first via searching I found this tutorial on replacing things at point and made this function:

; use string manipulation library to switch between camel and snake (s.el)
(defun my_test ()
  "test"
  (interactive)
  ;; get current selection or word
  (let (bds p1 p2 inputStr resultStr)
    ;; get boundary
    (if (use-region-p)
        (setq bds (cons (region-beginning) (region-end) ))
      (setq bds (bounds-of-thing-at-point 'word)) )
    (setq p1 (car bds) )
    (setq p2 (cdr bds) )
    ;; grab the string
    (setq inputStr (buffer-substring-no-properties p1 p2)  )
    (setq resultStr (s-lower-camel-case inputStr))
    (message inputStr)

    (delete-region p1 p2 ) ; delete the region
    (insert resultStr) ; insert new string
    )
)

This does not modify resultStr as expected and just repasts inputStr in there.

What I don't understand about this is that when I eval (with M-:) (setq resultStr (s-lower-camel-case "other_string")) I get the expected result ("otherString")

I even tried a different (and better for my purposes) way of writing the function inspired by this SO question:

(defun change-word-at-point (fun)
  (cl-destructuring-bind (beg . end)
      (bounds-of-thing-at-point 'word)
    (let ((str (buffer-substring-no-properties beg end)))
      (delete-region beg end)
      (insert (funcall fun str)))))

(defun my_test_camel ()
  (interactive)
  (change-word-at-point 's-lower-camel-case))

which suffers from the same problem. This makes me think that there is something wrong with the s-lower-camel-case function (or how I am calling it) but that works when called from eval as mentioned above

EDIT: modified first function to include let syntax, see comments

EDIT #2: Both of these functions work correctly, the answer has been accepted as it provides a better alternative with the information on symbol and the correct way of writing it. My problem was testing which was due to haskell-mode. New question is here

like image 206
Mike H-R Avatar asked Aug 07 '14 17:08

Mike H-R


People also ask

How do I replace in Emacs?

Simple Search and Replace Operations When you want to replace every instance of a given string, you can use a simple command that tells Emacs to do just that. Type ESC x replace-string RETURN, then type the search string and press RETURN. Now type the replacement string and press RETURN again.

How do I lisp in Emacs?

In a fresh Emacs window, type ESC-x lisp-interaction-mode . That will turn your buffer into a LISP terminal; pressing Ctrl+j will feed the s-expression that your cursor (called "point" in Emacs manuals' jargon) stands right behind to LISP, and will print the result.

Is Emacs Lisp the same as Lisp?

Emacs Lisp is a dialect of the Lisp programming language used as a scripting language by Emacs (a text editor family most commonly associated with GNU Emacs and XEmacs). It is used for implementing most of the editing functionality built into Emacs, the remainder being written in C, as is the Lisp interpreter.

What does #' mean in Emacs Lisp?

function (aka #' ) is used to quote functions, whereas quote (aka ' ) is used to quote data.


1 Answers

Here's an alternate definition. The comment was correct that you need to do local bindings via let. Note that this version uses the region if it's active, or else uses bounds-of-thing-at-point to get the word at point if no region is active:

(defun word-or-region-to-lcc ()
  "Convert word at point (or selected region) to lower camel case."
  (interactive)
  (let* ((bounds (if (use-region-p)
                     (cons (region-beginning) (region-end))
                   (bounds-of-thing-at-point 'symbol)))
         (text   (buffer-substring-no-properties (car bounds) (cdr bounds))))
    (when bounds
      (delete-region (car bounds) (cdr bounds))
      (insert (s-lower-camel-case text)))))

If you didn't care about the option to use region, you could bind text locally to (thing-at-point 'symbol) instead of the call to buffer-substring-no-properties.

UPDATE. It turns out you can use (thing-at-point 'symbol) rather than (thing-at-point 'word) to get the full symbol for snake case.

like image 100
Dan Avatar answered Oct 04 '22 17:10

Dan