在 emacs 中移动区域或行

发布于 2024-09-07 23:45:36 字数 476 浏览 7 评论 0原文

我正在 emacs 中寻找一种将文本向右或向左移动 n 个空格的方法。与 vim <<>> 中的功能类似。它应该在一个区域上工作,或者如果当前行上没有选择任何区域,并且不会将光标从当前位置移动。

EmacsWiki 的解决方案效果不如 Mx indent-rigidly 因为它会记住最后使用的区域并移动该区域。最接近的似乎是这里,但我没能做到让它发挥作用。我不是 Lisp 开发人员,因此很难修改代码。我将不胜感激任何帮助。

谢谢!

I'm looking for a way in emacs to shift text to the right or to the left by n spaces. A similar functionality that it in vim << or >>. It should work on a region or if no region is selected on a current line and not move the cursor from its current location.

The solution from EmacsWiki does not work very well as the M-x indent-rigidly since it somewhat remembers the last region used and shifts that one instead. The closest seems to be the one here but I did not managed to make it work. I'm not a lisp developer so it's difficult to modify the code. I will appreciate any help.

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

笑咖 2024-09-14 23:45:36

您可以选择区域,然后 Cu Cx 将移动 4 个空格。您可以在 Cu 后面键入一个数字,将 4 更改为其他任何值。

You could select the region then C-u C-x <tab> will shift 4 spaces. You can type a number after C-u to change 4 to anything else.

溺深海 2024-09-14 23:45:36

也许这会按照你想要的方式工作。

(defun shift-text (distance)
  (if (use-region-p)
      (let ((mark (mark)))
        (save-excursion
          (indent-rigidly (region-beginning)
                          (region-end)
                          distance)
          (push-mark mark t t)
          (setq deactivate-mark nil)))
    (indent-rigidly (line-beginning-position)
                    (line-end-position)
                    distance)))

(defun shift-right (count)
  (interactive "p")
  (shift-text count))

(defun shift-left (count)
  (interactive "p")
  (shift-text (- count)))

Maybe this works the way you want.

(defun shift-text (distance)
  (if (use-region-p)
      (let ((mark (mark)))
        (save-excursion
          (indent-rigidly (region-beginning)
                          (region-end)
                          distance)
          (push-mark mark t t)
          (setq deactivate-mark nil)))
    (indent-rigidly (line-beginning-position)
                    (line-end-position)
                    distance)))

(defun shift-right (count)
  (interactive "p")
  (shift-text count))

(defun shift-left (count)
  (interactive "p")
  (shift-text (- count)))
浪荡不羁 2024-09-14 23:45:36

为了实现这一点,我通常会采取一个技巧:

  • 激活 CUA 模式,
  • 转到 C-RET 行的开头
  • ,现在如果移动光标,您应该会看到一个矩形红色区域
  • 将光标向下移动并键入空间,直到获得正确的变速。

这也可以通过某种方式(以相同的方式)以编程方式完成。

编辑:
我刚刚读过 emacs wiki 中的文章,它是相同的解决方案,除了 CUA 模式,它比“常见”矩形选择(因为它是可视的)更强大。

To achieve this I usually do a trick:

  • activate CUA mode
  • go to the beginning of line
  • C-RET, now if you move the cursor you should see a rectangular red region
  • Move the cursor down the lines and type space until you've obtained the correct shifting.

This can be done also programmatically in some way (in the same way).

EDIT:
I've just read the article in emacs wiki, it's the same solution except for the CUA mode that is infinitely more powerful than the "common" rectanguar selection (since it's visual).

长梦不多时 2024-09-14 23:45:36

当我使用 Evil (与 Doom Emacs),类似 Vim 的区域移动已经在邪恶的视觉模式中通过 Sv</ 实现> 正确。

不过,我主要使用插入模式,当它处于活动状态时,我也希望能够移动区域,最好是通过当前语言的移动宽度。

为了实现这一目标,这里有一个重新使用邪恶转移的实现,但在插入模式中“正确”地实现了它。

(defun jj/shift-text (beg end shift-block-fun shift-line-fun)
  "shift text in region or line using evil like S-v with < and > do in Vim.
  It takes special care of preserving or even extending the region to the moved text lines."
  (if (use-region-p)
      (progn
        (let ((point-at-end (< (mark) (point))))

          ;; fix up current region end to grab the whole line
          (if point-at-end
              (end-of-line)
            (beginning-of-line))

          ;; then fix up the other region end
          (exchange-point-and-mark)
          (if point-at-end
              (beginning-of-line)
            (end-of-line))

          ;; restore mark-point order
          (exchange-point-and-mark)

          (let ((linebeg (if point-at-end (mark) (point)))
                (lineend (if point-at-end (point) (mark))))
            ;; shift the text
            (save-mark-and-excursion
              (funcall shift-block-fun linebeg lineend)
              ;; "In Transient Mark mode, every buffer-modifying primitive sets deactivate-mark"
              ;; but we wanna keep it active :)
              (setq deactivate-mark nil)))))

    (funcall shift-line-fun 1)))

(defun jj/shift-left (beg end)
  (interactive "r")
  (jj/shift-text beg end #'evil-shift-left #'evil-shift-left-line))

(defun jj/shift-right (beg end)
  (interactive "r")
  (jj/shift-text beg end #'evil-shift-right #'evil-shift-right-line))

以及定义键绑定的位置:

  ;; text shifting. evil-normal-state-map has these anyway.
  (define-key evil-hybrid-state-map (kbd "M-<") #'jj/shift-left)
  (define-key evil-hybrid-state-map (kbd "M->") #'jj/shift-right)

As I use Evil (with Doom Emacs), the Vim-like region shifting is already implemented in evil's visual mode with S-v and </> properly.

I'm mostly using insert-mode though, and when it's active I also want to be able to shift the region, preferrably by the current language's shift-width.

To achieve this, here's an implementation that re-uses evil's shifting, but does it "properly" in insert-mode.

(defun jj/shift-text (beg end shift-block-fun shift-line-fun)
  "shift text in region or line using evil like S-v with < and > do in Vim.
  It takes special care of preserving or even extending the region to the moved text lines."
  (if (use-region-p)
      (progn
        (let ((point-at-end (< (mark) (point))))

          ;; fix up current region end to grab the whole line
          (if point-at-end
              (end-of-line)
            (beginning-of-line))

          ;; then fix up the other region end
          (exchange-point-and-mark)
          (if point-at-end
              (beginning-of-line)
            (end-of-line))

          ;; restore mark-point order
          (exchange-point-and-mark)

          (let ((linebeg (if point-at-end (mark) (point)))
                (lineend (if point-at-end (point) (mark))))
            ;; shift the text
            (save-mark-and-excursion
              (funcall shift-block-fun linebeg lineend)
              ;; "In Transient Mark mode, every buffer-modifying primitive sets deactivate-mark"
              ;; but we wanna keep it active :)
              (setq deactivate-mark nil)))))

    (funcall shift-line-fun 1)))

(defun jj/shift-left (beg end)
  (interactive "r")
  (jj/shift-text beg end #'evil-shift-left #'evil-shift-left-line))

(defun jj/shift-right (beg end)
  (interactive "r")
  (jj/shift-text beg end #'evil-shift-right #'evil-shift-right-line))

and where your keybindings are defined:

  ;; text shifting. evil-normal-state-map has these anyway.
  (define-key evil-hybrid-state-map (kbd "M-<") #'jj/shift-left)
  (define-key evil-hybrid-state-map (kbd "M->") #'jj/shift-right)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文