Can we know, that we are in the following position:

text1 ... <cursor> ... text2

But this doesn't count:

text1 ... text2 ... <cursor> ... text2

text1 ... <cursor> ... text1 ... text2

Here's a function that takes two arguments, and returns t if the text before point is TEXT-BEFORE and the text after is TEXT-AFTER.

(defun in-between-p (text-before text-after)
  "Return t if point is directly between TEXT-BEFORE and TEXT-AFTER."
  (and (first-text-comes-closer-to-point-than-second-before-point text-before text-after)
       (first-text-comes-closer-to-point-than-second-after-point text-after text-before)))

(defun first-text-comes-closer-to-point-than-second-before-point (first-text second-text)
  (and (looking-back (format "%s.*" (regexp-quote first-text))) ;;first-text appears before point

       (let ((first-text-match-position (match-beginning 0)))

         (or (not (looking-back (format "%s.*" (regexp-quote second-text)))) ;;either second-text isn't before point
             (< (match-beginning 0) ;;or it's before first-text

(defun first-text-comes-closer-to-point-than-second-after-point (first-text second-text)
  (and (looking-at-p (format ".*%s" (regexp-quote first-text)))
       (let ((first-text-match-position (match-beginning 0)))
         (or (not (looking-back (format ".*%s" (regexp-quote second-text))))
             (> (match-beginning 0)

And here's a way to test it interactively.

(defun between-rock-and-hard-place (rock hard-place)
  (interactive (list (read-string "string before: ")
                     (read-string "string after: ")))
  (if (in-between-p rock hard-place)
      (message "you're between them")
    (message "you have different neighbors")))

Evaluate these two functions, then type something in a buffer. For example:


I'm using the | character to represent point.

Then you can call M-x between-rock-and-hard-place, which will prompt for two strings. If, for example, you input abcd and efgh in that order, you'll get the message "you're between them". If you input something like "bcd" and "BAD TEXT", you'll get the "you have different neighbors" message.

It won't match across newlines right now, but I'll try to fix that tomorrow.

| improve this answer | |
  • Unfortunately, this won't work. looking-back predicate won't omit the text. Say, we have the situation: text1 blah blah <cursor> blah text2 - this is valid, but in-between-p will return nil. Plus, how can we omit text1 ... text2 ... <cursor> ... text2 situations? – user4035 Nov 13 '15 at 4:50
  • Can you give a more specific example? You don't care if text1 appears directly before point, just that it appears somewhere before point, and text2 doesn't appear between text1 and point? – zck Nov 13 '15 at 4:54
  • Yes, And text1 doesn't appear between cursor and text2. I wanted to use this function to determine, that the cursor is inside array( ... ) in PHP code – user4035 Nov 13 '15 at 4:59

In the comments to @zck:s answer, you say that you want to find out if the point is in a php array construct. The following does this, with the limitation that the point must not be inside a parenthesized subexpression.

(defun my-in-php-array ()
  "Return non-nil if the point is inside a php array construct."
    (and (ignore-errors
         (eq (char-after) ?\(  )
         (looking-back "\\<array[ \t]*"))))
| improve this answer | |

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.