Emacs行高

17

我正在尝试在Emacs缓冲区中设置文本的行高,以使字母上下有空间。根据文档,我推断line-height文本属性可能会帮助我实现这一点。

还有一个line-spacing变量,可以像(setq-default line-spacing 0.25)这样设置。它有点起作用,但是只会在文本之后产生空间,而不是之前。当使用像show-paren-mode这样的模式时,我不喜欢它的外观,因为它会“下沉”:

当前不希望出现的行为(“悬挂”)

当前不希望出现的行为

期望的行为模拟(垂直居中)

期望的行为

我想要将文本垂直居中。

我发现可以使用以下代码暂时达到我想要的效果:

(add-text-properties (point-min) (point-max)
                     '(line-spacing 0.25 line-height 1.25))

但是,在某些模式下,当我开始输入时,属性会在区域中消失。我该如何使顶部和底部间距成为默认值?(钩子无效)


我在尝试使用(setq-default line-spacing 0.25)(show-paren-mode 1)来复制的蓝色背景条时遇到了困难。您能否请稍微澄清一下您所说的*(setq-default line-spacing 0.25) . . . 不会在文本之前产生空格,只会在文本之后产生空格*是什么意思? - lawlist
0.25 的情况下可能有些难以看清。在上面的截图中,我使用了 1.0。使用 emacs -q 和 M-: (show-paren-mode 1) 以及 M-: (setq-default line-spacing 1.0) 应该会产生高大的竖杠。 - Jackson
1
在文档中,它说“首先Emacs使用高度作为高度规范来控制行上方的额外空间”,但是正如您在上面的截图中所看到的,额外的空间仅在单词后添加。我想要获得文档所提到的“行上方的额外空间”,使得上面的蓝色条向上延伸的额外像素数量只有当前向下延伸的一半,以使文本在蓝色条内垂直居中。 - Jackson
添加了一些更好的截图来展示这个。 - Jackson
3个回答

8

更新

简要概述:我已经认识到无法在Emacs中通过本地方法可靠地实现这一点。您需要修补字体本身以包含额外的间距。因此,我创建了这个脚本来解决这个问题。


旧/不完整的回答

简要概述:在init文件的某个位置添加以下内容:

;; Set the padding between lines
(defvar line-padding 3)
(defun add-line-padding ()
  "Add extra padding between lines"

  ; remove padding overlays if they already exist
  (let ((overlays (overlays-at (point-min))))
    (while overlays
      (let ((overlay (car overlays)))
        (if (overlay-get overlay 'is-padding-overlay)
            (delete-overlay overlay)))
      (setq overlays (cdr overlays))))

  ; add a new padding overlay
  (let ((padding-overlay (make-overlay (point-min) (point-max))))
    (overlay-put padding-overlay 'is-padding-overlay t)
    (overlay-put padding-overlay 'line-spacing (* .1 line-padding))
    (overlay-put padding-overlay 'line-height (+ 1 (* .1 line-padding))))
  (setq mark-active nil))


(add-hook 'buffer-list-update-hook 'add-line-padding)

根据您的喜好增加或减少line-padding值。

本回答基本上总结了上述问题、答案和评论中的信息,建议先阅读那些内容。

我使用覆盖层而不是文本属性,因为在向缓冲区添加新文本时(特别是通过复制/粘贴),它会更好地表现。

buffer-list-update-hook被用作标识新缓冲区已创建并需要应用覆盖层的手段。

出于性能原因,为了不断地添加覆盖层,如果已经存在,则删除现有填充覆盖层。


这个方案可行,但是模式栏和一些缓冲区(如helm和org-agenda缓冲区)除外。有没有办法使这个行高全局生效? - Choma
1
我已经认识到目前emacs并没有很好地支持这一点。我使用字体编辑器Font Forge在字体顶部和底部添加了额外的填充,并且使用了一段时间,没有遇到任何问题。 - tam5
这个解决方案感觉像是一个不错的开端,但仍有很长的路要走。我发现当编辑文本时,行高度有时会从默认值短暂调整到自定义值。而且,代表当前点的“闪烁正方形东西”(“光标”?不知道该怎么称呼)的高度会根据点是否在空格或非空格处而改变。这两种行为都会让我分心,可惜了。 - Jackson
你可以使用 remove-overlays 来简化你的代码。 - Stefan

7
正如文档所述,line-height是一个文本(或覆盖层)属性,而不是变量。
尝试使用(setq-default line-spacing 20)line-spacing是一个框架参数或缓冲区本地变量。其值可以是像素的整数或指定相对于帧默认行高度的间距的浮点数。文档没有说明可以给它一个列表值,例如(32 64)
如果您在终端模式下使用Emacs,则以上内容均不适用。正如文档所述:
On text terminals, the line spacing cannot be altered.

实际上,文档中说:“如果属性值是形如(高度总计)的列表”,这意味着它可以是一个列表。 - Jackson
或许有一种方法可以真正地设置行高?我尝试过(set-face-attribute 'default nil :height 128),这使得字体相对变大了,但是还是存在同样的悬挂问题。(set-face-attribute 'default nil :height '(128 256))会产生错误信息:(error "Default face height not absolute and positive" 128 256) - Jackson
(set-face-attribute 'default nil :line-height 128)(set-face-attribute 'default nil :line-height '(128 256)) 都会抛出 (error "Invalid face attribute name" :line-height) 错误... 这个 "text property" 在哪里配置的呢? - Jackson
我所说的是文档中没有提到将**line-spacing**赋予列表值。这就是事实——对于帧参数、文本/叠加属性和变量而言都是如此。你可能将line-spacingline-height混淆了。 - Drew
line-height是文本或叠加属性。:line-height不是。你真的需要更加注意文档 - 也许在阅读时放慢一点速度。此外:如果你使用M-x customize-faceM-x customize-option,你可能不太可能弄错名称,因为标准面部属性被呈现,并且可能的选项值在某种程度上受到控制。至少对于测试,尝试使用自定义 - 它可以提供一些帮助,我认为。无论如何,我已经解释了如何增加行间距(使用line-spacing,将其传递给一个数字)。 - Drew
多年前我们曾经谈论过这个话题,当时我并不真正理解文本属性是什么。自那以后,我学到了它是一个名值对,人们可以使用put-text-property等函数为某个字符设置属性。 (作为本主题读者的参考点。) - Jackson

1
尝试点击 "帮助 => 更多手册 => Emacs Lisp参考",然后输入 "i text properties RET"。这将有望澄清情况。至于您的具体要求,我认为目前没有简单的方法来得到您想要的内容。您可以尝试使用 "M-x report-emacs-bug" 报告括号高亮显示的显示外观问题。

经过多年的学习,我终于完全理解了文本属性和变量之间的区别。我更新了问题以消除这种混淆。 - Jackson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接