Search code examples
emacsselectionregion

Emacs Lisp make region selected by start and end after changing buffer


I would like to have a emacs function which selects (marks) a region given by start and end. I tried it with

(defun mark-range (start end)
  "Mark buffer content from start to end"
  (message (concat "Select " (number-to-string start) " " (number-to-string end)))
  (setq bufmax (max start end))
  (setq bufmin (min start end))
  (goto-char bufmax)
  (set-mark bufmin) ;actually the comment on set-mark says: Do not use!

  ;(set-mark-command bufmin) did not work for this
)

It works when called in simple functions, but sometimes this function just does not work even when the message shows the right content of start and end. The selection is then just not there.

Any Ideas, how I can achieve a reliable function? (I am using spacemacs dev branch)

EDIT: Ok here is the use case, I actually want to move text up and down with Alt-Up Alt-Down like it is in eclipse

I found there is a block move text, but it does not what I want: Select the full lines the region touches and moves it up afterwards staying selected to be used again.

So I first check how many lines I must move the line before the first down, and then use this also to select the lines again. But then the selection does not work. It is simply not there.

I now tried to integrate Drews answer but did not really help, mark does not appear, (added deactivate-mark as there is one before, also no luck). Tried it with my approach including (activate, deactivate) before, also does not work.

(defun rl-move-up-block(start end)

  (let (last first dist m-start)
  (goto-char (max start end))
  (setq last (line-number-at-pos))

  (goto-char (min start end))
  (setq first (line-number-at-pos))

  (goto-char (min start end))
  (forward-line -1)

  (setq dist (+ (- last first) 1))

  (dotimes (i dist)
    (move-text-line-down))


  (forward-line (- 0 dist))
  (set-mark (line-beginning-position))
  (forward-line (- dist 1))
  (end-of-line)
  (activate-mark)
 )
)

(defun rl-move-up (start end)
  "Move text up like in eclipse"
  (interactive "r")
  (if (use-region-p)
      (rl-move-up-block start end)
    (move-text-line-up)
    )
  )

(global-set-key (kbd "M-<up>") 'rl-move-up)

EDIT 2: Well I just found out if I remove the moving of the lines, replacing it with just moving the cursor, marking works just fine.

  ;(dotimes (i dist)
  ;  (move-text-line-down))
  (forward-line dist)

So the issue is changing text and then marking again. I once tried to have a view what it does in slow mo, by putting a sleep between each line.

Did not work, just made the whole function take longer - maybe it needs a refresh view call for something. Is there something to refresh or finalize a change? Maybe that helps to make mark work again after moving lines.


Solution

  • Well turns out there is a variable.

    I checked the code of move-text-down a existing command and found there is a variable set to nil If I do that after moving text it works

    
      (dotimes (i dist)
        (move-text-line-down)) 
    
        (setq deactivate-mark nil) ; <<<<<<
    
        (forward-line (- 0 dist))