1

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.

2
  • Does calling (activate-mark) fix the cases where it doesn't work? If not, show us a case in which it doesn't work (otherwise we have to guess how to reproduce the problem). Commented Sep 19, 2019 at 21:46
  • Use let rather than setq to establish your temporary variables. With setq they will persist beyond the scope of the function call. Commented Sep 19, 2019 at 21:48

2 Answers 2

1

You were just missing function activate-mark.

The doc says that set-mark sets the mark, and that sometimes people do that unnecessarily. Here you explicitly want to set the mark at an arbitrary position (the least of START or END).

You also want to call message last.

(defun mark-range (start end)
  "..."
  (set-mark (min start end))
  (goto-char (max start end))
  (activate-mark)
  (message "Select %d to %d" start end))
Sign up to request clarification or add additional context in comments.

1 Comment

Actually your function works as well as mine but not in combination with the changes. The change (moving lines) seems to be the problem. (see my second edit)
1

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))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.