views:

61

answers:

2

Is there a native Emacs Lisp function that behaves like strpos() in PHP? It should return the position of first occurrence of the given string in current buffer. Function search-forward is nice, but it modifies the character position.

+2  A: 

You can do:

;; does not modify match-data
(string-match-p (regexp-quote "string") (buffer-string))

or

;; does modify match-data
(string-match (regexp-quote "string") (buffer-string))

But those calls make a copy of the string, which isn't practical. A better solution would be to use this:

(defun my-strpos (string)
  "mimic strpos"
  (save-excursion
    (save-match-data
      (goto-char (point-min))               ; or not
      (when (search-forward string nil t)
        (match-beginning 0)))))

It also depends on what you want to do after finding the position. The documentation for match data might be useful. If you want to use the match-data afterwords, remove the call to 'save-match-data.

Trey Jackson
`(buffer-string)` makes a copy of the buffer contents, so it's not practical for large buffers.
Gilles
@Gilles - very true, I'll add a note indicating that, I should have originally. Thanks.
Trey Jackson
I came to a solution just as your code in the end. Thanks.
Török Gábor
+3  A: 

The function corresponding to strpos in PHP, to search for a string inside another string, is search from the cl package:

(require 'cl)
(search needle haystack :start2 offset)

If you want to search a string inside a buffer, use search-forward. Since this changes the current buffer and the point inside that buffer, you need to wrap your function inside save-excursion; this is a common Emacs Lisp idiom. You should also wrap your function in save-match-data, so as not to interfere with the searches of whatever calls your code.

(save-match-data
  (save-excursion
    (set-buffer haystack)
    (goto-char (or offset (point-min)))
    (let ((pos (search-forward needle nil t)))
      ...)))
Gilles