写一个move-line-up函数时碰到了问题

需求:把一行/多行上移prefix-arg行

目标是一行时不难实现:

(defun jjpandari/move-line-up (count)
  "Move prefix-arg lines up."
  (interactive "p")
  (dotimes (i count) (move-text-line-up))
  )

考虑目标是多行的情形,借鉴这里:

我改成了:

(defun jjpandari/move-line-up (count)
  "Move prefix-arg lines up."
  (interactive "p")
  (save-restriction
    (if (region-active-p)
        (goto-char (point-min))
      (while (< (point) (point-max))
        (next-line)
        (when (< (point) (point-max))
          (dotimes (i count) (move-text-line-up))))
      (dotimes (i count) (move-text-line-up)))))

并没有正常工作,甚至还会卡死emacs。请坛友们指点。改进了,请看4楼

  1. 你的代碼槽點太多,比如按你這個來,沒选中的時候只会跳到第一行,別的什麼都沒干。原因是你沒搞清楚 if 的行為。
  2. 會卡是因爲你大量调用了 (move-text-line-up),开銷太大。
  3. 內置就有 move-text-region。对照著看,差不多应該知道问題在哪。
;;;###autoload
(defun move-text-region (start end n)
  "Move the current region (START END) up or down by N lines."
  (interactive (move-text-get-region-and-prefix))
  (let ((line-text (delete-and-extract-region start end)))
    (forward-line n)
    (let ((start (point)))
      (insert line-text)
      (setq deactivate-mark nil)
      (set-mark start))))

Q: 一位精神病患者,医生想看一下他是否康复了,于是就把浴缸里的水放满了给了他一个勺子和一个碗,让他把里面水放完,应該怎麼做?

A: 拔掉塞子

if用错了。

现在region-p时改成

(move-text-region-up (region-beginning) (region-end) count)

基本可以了,只是内容移动后选中部分会留在原来的地方,无论加不加save-restriction

1 个赞

我又去抄了一下evil-indent,感觉现在应该算比较像样了,不过又碰到个疑问(注释部分本来是启用的,这里为了说明问题注释掉它们):

(defun jjpandari/move-line-up (count)
  "Move prefix-arg lines up."
  (interactive "p")
  (if (region-active-p)
      (let* ((beg (region-beginning))
             (end (region-end))
             (beg-line (line-number-at-pos beg))
             (end-line (line-number-at-pos end))
             (line-count (1+ (- end-line beg-line))))
        (move-text-up beg end count)
        (goto-char (point-min))
        ;; (forward-line (- beg-line count))
        ;; (indent-region (point) (line-beginning-position (+ 1 line-count)))
        )
    (move-text-up (line-beginning-position) (line-beginning-position 2) count)
    (deactivate-mark)
    (indent-for-tab-command))
  )

注意看ifTHEN部分,除了let*的赋值外,只有move-text-up(goto-char (point-min)),我期待的是执行后会跳到buffer开头,然而move-text-up正常,goto min却没有起作用,求指点。