Emacs是否有自动对齐程序包或模式?


15

有时候,我在编辑文件(例如,Puppet清单)时要动态对齐缓冲区内容。例如,我知道只要选择以下代码,就可以使用align-regexpalign对齐代码:

# M-x align-regexp "=>" will line everything up nicely 
file { "/etc/foo":
  ensure => present,
  mode => "0666",
  source => "puppet:///modules/example/foo",
}

但是我真正想要的是让这种情况即时发生-无需选择区域或整个缓冲区。是否有可以执行此操作的程序包或模式,或者是否必须将这些内容内置到我感兴趣的模式中?

编辑:我问了有关Puppet和CFEngine的问题,因为这是我最近几天编写的代码,并且我非常喜欢对齐的文本。但是,我也很好奇(并没有很好地表达这一点)想知道即时对齐是否是Emacs模式(主要是用于编程语言的模式)中常见的功能,或者大多数人在保存时或在某些情况下会对齐吗?其他一点。


expand-region,对于连续选择更大的范围很有用。
bastibe 2014年

1
您能否进一步说明通常要达成的目标?它只是等号而且处于人偶模式吗?您可以通过@Malabarba 修改此Emacs SE答案中的代码以进行自动缩进,以获取所需的内容。只需替换为indent-regionalign-to-equals然后将此函数定义为(defun align-to-equals (begin end) (interactive "r") (align-regexp begin end "\\(\\s-*\\)=" 1 1 nil));并emacs-lisp-mode-hookpuppet-mode-hook
Kaushal Modi 2014年

Answers:


5

如果您想标记一个区域以进行自动对齐,那么执行以下操作可能不太困难:

(require 'cl-lib)

(defvar my--auto-align-overlays nil)
(make-variable-buffer-local 'my--auto-align-overlays)

(defun my-auto-align (beg end regexp)
  (interactive "r\nsRegexp: ")
  (let ((ol (make-overlay beg end)))
    (overlay-put ol 'evaporate t)
    (overlay-put ol 'my--auto-align-regexp regexp)
    (overlay-put ol 'modification-hooks '(my--auto-align-function))
    (push ol my--auto-align-overlays)
    (add-hook 'post-command-hook 'my--auto-align-pch nil t)))

(defun my--auto-align-function (ol &rest _args)
  (cl-pushnew ol my--auto-align-overlays)
  (add-hook 'post-command-hook 'my--auto-align-pch nil t))

(defun my--auto-align-pch ()
  (dolist (ol my--auto-align-overlays)
    (align-regexp (overlay-start ol) (overlay-end ol)
                  (concat "\\(\\s-*\\)" (overlay-get ol 'my--auto-align-regexp))
                  1 align-default-spacing))
  (setq my--auto-align-overlays nil)
  (remove-hook 'post-command-hook 'my--auto-align-pch))

但是,如果您希望它是全自动的,则需要找到一种方法来表征要自动对齐的区域(以及与哪个正则表达式),这比较困难。我猜您可以提供一些正则表达式,然后在缓冲区中扫描与那些正则表达式之一匹配的连续行。


我以前没有使用过叠加层,但是Elisp手册似乎说它们是用于改变外观的-我知道吗?如果是这样,是否意味着此答案只会更改缓冲区的外观,而不是更改文件保存后的实际内容?(这是我一直在寻找的后者,但是更改外观将是一个有趣的选择。)
圣地毯地毯的奥德瓦克

2
@SaintAardvarktheCarpeted叠加层通常用于更改外观,但其适用范围不止于此。在此答案(IIUC)中,覆盖层用于标记要对齐的区域(因此缓冲区确实发生了变化,而不仅仅是外观)。该函数my-auto-align用于定义这些覆盖图(标记要对齐的区域)。Stefan经历了所有这些麻烦的原因是(与缩进不同)(如果只是尝试对齐整个缓冲区),您会得到不想要的结果,因此您需要一次对齐碎片。
马拉巴巴2014年

3

木偶模式提供puppet-align-block。您可以安排自动调用此函数,例如,将其添加到post-command-hook本地(未调试):

(defun puppet-auto-align ()
  (unless (puppet-in-string-or-comment-p)
    (puppet-align-block)))

(define-minor-mode puppet-auto-align-mode
  :init-value nil
  :keymap nil
  :lighter "PAl"
  :group 'puppet-lint
  (if puppet-auto-align-mode
      (add-hook 'post-command-hook #'puppet-auto-align nil 'local)
    (remove-hook 'post-command-hook #'puppet-auto-align 'local)))

(add-hook 'puppet-mode-hook #'puppet-auto-align-mode)

但是请注意,有充分的理由不这样做。它不是特别聪明,并且会覆盖您可能在任何地方执行的任何手动对齐方式,如果自动对齐方式对某些更复杂的Puppet代码不起作用,则这种对齐方式将严重破坏。

因此,我建议您反对使用它作为Puppet Mode维护者,如果您使用此代码,我们将不帮助您或接受错误报告。

另外,对于大资源块,它可能很慢,因此您可能想使用空闲计时器而不是post-command-hook直接使用它。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.