Search code examples
emacselisp

How do I get the region (selection) programmatically in Emacs Lisp?


I need to access the selection in Emacs buffer. I have found this article How do I access the contents of the current region in Emacs Lisp? and it helps me a lot.

But there is a problem. The first time I select (highlight) a region, it works okay, but when I press C-g, and move cursor normally to another place without highlighting any chars, I got a string from last mark to the current point while I expect an empty one.

Actually I need to implement a function which will return the current selection (highlighted) as a string, or empty string if nothing is highlighted. The following code may express me more clearly.


(defun get-search-term ()
  (interactive)
  (let (
        (selection (buffer-substring-no-properties (region-beginning) (region-end))))
    (if (= (length selection) 0)
        (message "empty string")
      (message selection))))

Any suggestions? Thanks a lot!


Solution

  • "r" specification of interactive is dumb. You're seeing why.

    (defun get-search-term (beg end)
      "message region or \"empty string\" if none highlighted"
      (interactive (if (use-region-p)
                       (list (region-beginning) (region-end))
                     (list (point-min) (point-min))))
      (let ((selection (buffer-substring-no-properties beg end)))
        (if (= (length selection) 0)
            (message "empty string")
          (message selection))))
    

    I don't mean "dumb" as in stupid and not useful; just that it doesn't care about whether the mark is active or not. I think it predates transient-mark-mode.

    EDIT: Using (point-min) twice above makes the code harder to understand when re-reading. Here is a better implementation:

    (defun get-search-term (beg end)
      "message region or \"empty string\" if none highlighted"
      (interactive (if (use-region-p)
                       (list (region-beginning) (region-end))
                     (list nil nil)))
      (message "%s" (if (and beg end)
                        (buffer-substring-no-properties beg end)
                      "empty string")))