1

I am writing a function to select a region (say 2 lines).

(defun select-some-region ()
  (interactive)
    (push-mark (point) nil t)
      (forward-line 2))

When point is in a buffer like this

 |this is first
 this is second
 this is third

If I run M-x select-some-region it will select two line and I press C-g it will deselect the region but leaves point somewhere else like this.

 this is first
 this is second
 |this is third

How can I leave point in actual position where it was before when C-g is pressed?

Update:

In my actual select-some-regions function, I have to select few lines before point and few lines after point.

  • You could just perform point movement in reverse order. I.e. forward line first, while remembering where the point was before you moved, and then push mark to the position you remembered. – wvxvw Sep 19 '15 at 12:50
  • Excatly, but how can i detect that user has pressed C-g? – ChillarAnand Sep 19 '15 at 12:59
  • 1
    There's a fairly new package smart-mark added to Melpa. That might do what you want. – Kaushal Modi Sep 19 '15 at 13:39
  • @kaushalmodi You can post it as solution as it solves the problem. That package is using advice-add but i guess there are much better solutions as packages like exapand-region, web-mode do the same without advice. – ChillarAnand Sep 19 '15 at 16:09
  • @ChillarAnand Actually smart-mark package might not be applicable here as you would need to customize the smart-mark-mark-functions var and add every function in there for which you need the "smart mark" functionality. I use the package to resolve one minor annoyance: Doing C-x h and restoring mark after C-g. The advices in that package have not harmed me in any way till now so I wouldn't say that that approach is not better :) It's great as it works for me right out of the box. – Kaushal Modi Sep 21 '15 at 2:11
1

The function keyboard-quit is just a few lines of code in simple.el, which can either be redefined or otherwise tweaked/modified to suit the user's needs. The following answer uses defacvice: If beginning of the region is less than point, this means that the region was marked from left to right, so go to the beginning of the region. If not, the region was marked from right to left, so go to the end of the region.

(defadvice keyboard-quit (before keyboard-quit-before activate)
  (when (region-active-p)
    (let* (
        (pt (point))
        (beg (region-beginning))
        (end (region-end)) )
      (if (< beg pt)
        (goto-char beg)
        (goto-char end)))))
  • Redefining keyboard-quit seems (to me) like a particularly dodgy idea. I'd be curious to hear a maintainer's opinion on doing this. I wouldn't recommend it, but that's mostly gut instinct. – phils Sep 21 '15 at 6:00
  • @phils -- the majority of Emacs users treat the source-code as sacred/holy -- i.e., it is a cult following -- but I think in terms of blasphemy in that it's just plain code to be manipulated as I see fit. I have custom functions for just about everything that I use on a daily basis, including keyboard-quit and keyboard-escape-quit -- I have custom files, custom dired, custom tramp, custom org, custom calendar, custom tex, custom elisp-mode, custom wanderlust and related libraries, custom just about everything . . . :) – lawlist Sep 21 '15 at 6:08
  • 1
    I agree with @phils : I don't think it's so much blind obedience to dogma, but rather that if you modify fundamental functions the knock-on effects could be wide-ranging and unpredictable. Once you start editing primitives you will make it very hard for anyone else to help you isolate and correct problems arising as unintended consequences. – Tyler Sep 21 '15 at 15:23
1

C-g does not move the point, so there's no “original position” to restore. If you want the select-some-region function to preserve the point, write it in such a way that it does preserve the point. With the function in your question, you could invert the point and the mark.

(defun select-some-region ()
  (interactive)
  (save-excursion
    (forward-line 2)
    (push-mark (point) nil t)))

Alternatively, given your original function, you can easily return to the previous cursor position, since the mark is set there. Just press C-1 C-SPC (set-mark-command with the numeric argument 1).

  • I guess this will not work, when i want to select two lines before & two lines after cursor? – ChillarAnand Oct 7 '15 at 8:27
  • @ChillarAnand No, because in Emacs, the cursor is one of the boundaries of the selection, there's only one mark, not two like in Wordstar. – Gilles 'SO- stop being evil' Oct 7 '15 at 8:32
1

Can this help?

(defun select-some-region ()
  (interactive)
   (let ((this-point (point))) (forward-line 2)  (push-mark (point) nil t)
      (goto-char this-point) ))
  • (idea suggested by @wvxvw) – Name Sep 19 '15 at 15:48
  • This is good. I am actually trying to select few lines before point and few lines after point, so this doesn't work in required context – ChillarAnand Sep 19 '15 at 16:04
1

As it was mentioned, C-g does not move point by itself. You mentioned in a comment that the region you sets started before and ended after the current point position, hence you can not use the trick of keeping point where it is.

I think one way of dealing with this problem is to push mark at current position before marking the region. Then you can recover the previous point position by hitting C-u C-SPC twice. Example with mark-paragraph :

(defun my/mark-paragraph ()
  (interactive)
  (push-mark nil t)
  (call-interactively 'mark-paragraph))
0

After going through web-mode source code, i found this solution.

Store initial point in some variable in function. Write a function which moves point to that location when C-g is pressed. Now hook this function to post-command-hook

(defun select-some-region ()
  (interactive)
  (setq initial-pos (point))
  (push-mark (point) nil t)
  (forward-line 2))    

(defun move-point ()
  (when (eq this-command 'keyboard-quit)
    (goto-char initial-pos)))

(add-hook 'post-command-hook 'move-point)

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.