如何获取缓冲区(而不仅仅是文件)来兑现自动模式警报?


13

问:如何获取新的缓冲区以遵守其中的映射auto-mode-alist

找到文件时,Emacs会将文件扩展名与进行比较,auto-mode-alist以确定用于文件缓冲区的主要模式。有没有一种方法可以使用这些信息auto-mode-alist来确定尚无文件关联的缓冲区的模式?

那就是:如果我打开一个名称类似于文件扩展名的新缓冲区,是否可以使其以预期模式自动打开?例如,如果我要打开一个a-new-buffer.el尚未与文件关联的新缓冲区,我希望它以emacs-lisp-mode默认模式而不是默认模式打开。


2
只是好奇:用例是什么?IOW,为什么/何时/在什么情况下要这样做?通常,如果您希望将缓冲区与文件关联,然后从中选择其模式auto-mode-alist,则使缓冲区访问文件(这将处理所有事务)。
Drew

5
对我而言,典型的用例示例是:a)一个临时org缓冲区,用于测试我正在编写供其使用的新功能org-mode;b)临时R缓冲区,以进行一些快速的一次性统计操作;c)组成电子邮件的临时文本缓冲区。在每一种情况下,我希望创建一个文件来访问,我只是想扔掉的缓冲区,但是在适当的模式打开。

2
文件访问命令,如C-x C-f创建一个文件来访问 ”。这是一个基本的误解。他们只是完全按照您的要求进行操作。它是唯一的,如果当您尝试保存缓冲区,一个文件被创建。如果您不尝试保存缓冲区,则不会创建文件。就目前为止我所了解的,您想要的是“访问文件”(这实际上意味着以适当的模式打开缓冲区)。
提请2014年

8
像Dan一样,我一直都在不希望与实际文件路径关联的情况下创建临时缓冲区。可以访问伪造的文件路径,但是在选择目录(或接受当前目录)时至少会有一些摩擦。根据配置的其余部分,可能还会有其他副作用:自动保存行为?是否通过路径确定缓冲组或射弹项目?Ido确认提示?由于缓冲区无论如何都必须具有名称,因此使用该名称自动为临时缓冲区设置模式对我来说很有意义。
glucas 2014年

@Drew,是的,这是有道理的,它将是该问题的最简单答案-您可以将其发布为答案吗?它值得升级。

Answers:


8

文件访问命令(例如)C-x C-f 不会创建要访问的文件。他们做您想要的。

只有当您尝试 保存缓冲区时 ,才会创建文件

如果您不尝试保存缓冲区,则不会创建文件。就目前为止我所了解的,您想要的是访问文件(这实际上意味着以适当的模式打开缓冲区)。


4
如果您的手指过动,无论您想要什么,都会每3秒不断保存当前文件怎么办?
马拉巴巴2014年

1
@Malabarba:实际上,我确实有那个手指!;-)也许我们大多数人都会放屁-当事情一直崩溃时,这种习惯就重新出现了。但是无论如何,我按照我的建议去做:在一个废弃的访问文件缓冲区中进行编辑。如果我的过度活动的肌肉记忆妨碍了您并尝试保存,那就这样吧:要么我点击n不保存,要么(通常)我只是保存了缓冲区。然后我扔掉创建的文件...还是不扔。)
Drew

1
@Malabarba正是为了防止临时文件混乱,我开始使用特定于主要模式的暂存缓冲区。如果临时文件值得保留,则可以随时将其另存为文件。
考沙尔·莫迪

1
@kaushalmodi:什么都不用针对特定于模式的缓冲区,但是清除“ 临时文件的混乱 ”就像清除缓冲区混乱一样容易。;-)并且活动过度的手指在特定于模式的暂存缓冲区中会出现相同的问题,大概与在*scratch*以下情况中相同:当该手指自动击中时,系统会提示您进行保存C-x C-s
德鲁

9

如果已经使用Juri Linkov的解决方案多年了。

我创建类似的临时缓冲区C-x b test.org C-j。在major-mode通过经由文件扩展名来确定auto-mode-alist

;; http://thread.gmane.org/gmane.emacs.devel/115520/focus=115794
(setq-default major-mode
              (lambda () (if buffer-file-name
                          (fundamental-mode)
                            (let ((buffer-file-name (buffer-name)))
                          (set-auto-mode)))))

要测试效果,您可以尝试(prog1 (and (switch-to-buffer "my-new.org") major-mode) (kill-buffer "my-new.org")) => org-mode。干净以后emacs -q,测试就会回来fundamental-mode


1
太聪明了!它也比advice我一直使用的选项要整齐。不知道我要跟踪该(prog1...)部件的用途,但是该(setq-default major-mode ...)部件非常好。

1
随时查看Juri的Emacs网站。该prog1-test只是表明你的预期major-mode切换到缓冲区时。评估setq-default零件并运行测试。它将返回org-mode 如果没有setq-default它将返回fundamental-mode
拉斯莫斯2014年

这比我的buffer-list-update-hook更优雅。谢谢!
glucas 2014年

这应该是公认的答案,因为它实际上是在回答问题,而不是告诉我们我们为什么要问这个问题:)
Shlomi

6

通过使用来自@Drew的评论和@glucas的答案的想法,找出一种基于建议的方式,我将在此处记录它们,以防它们对任何人有用。

简短的版本:使用after建议来查询缓冲区是否具有关联的文件名,如果没有则临时设置一个文件名,然后让其余set-auto-mode机构负责细节。经过一些测试(不广泛),它似乎运行良好。

对于ido-switch-buffer和vanilla switch-to-buffer,两个建议是:

(defadvice ido-switch-buffer (after set-mode activate)
  (unless buffer-file-name
    (let ((buffer-file-name (buffer-name)))
      (set-auto-mode t))))

(defadvice switch-to-buffer (after set-mode activate)
  (unless buffer-file-name
    (let ((buffer-file-name (buffer-name)))
      (set-auto-mode t))))

我发现此选项对find-file@Drew提出的观点很有帮助,因为我的手指可以伸到我的大脑前面:肌肉记忆通常会使我进入完全切换到缓冲区的区域,而这完全find-file不会发生在我身上,这可以满足我的需要。现在,两个选项都可用。

更新:上面代码中的小错误,但可能会引起麻烦:每次切换到缓冲区时,它将重新运行缓冲区上的模式挂钩。下面为/tmp目录提供了实际的文件名,并避免了该问题:

(defadvice ido-switch-buffer (after set-mode activate)
  (unless buffer-file-name
    (setq buffer-file-name (concat "/tmp/" (buffer-name)))
    (set-auto-mode t)))

看起来不错,并清理了我在几次迭代中积累的答案。:-)在这里我只重复一遍,如果由于某种原因您不想设置实际的文件路径,则可以使用局部缓冲区变量来避免多次设置模式。
glucas 2014年

5

set-auto-mode功能根据与缓冲区关联的文件设置模式。这是一个buffer-file-name从缓冲区名称临时设置以设置模式的函数:

(defun my/set-buffer-mode (buffer &optional again)
  "Set the mode for BUFFER from the name.  
When called repeatedly for the same buffer only set the mode the first
time, unless the optional argument AGAIN is specified.
Does nothing if the buffer is associated with a file."

  (with-current-buffer buffer
    (when again (kill-local-variable 'my/buffer-mode-set))
    (unless (or buffer-file-name 
            (local-variable-p 'my/buffer-mode-set))
      (let ((buffer-file-name (buffer-name)))
        (set-auto-mode t)
        (setq-local my/buffer-mode-set t)))))

使用建议重命名缓冲区时,可以运行此命令:

(defadvice rename-buffer (after my/rename-update-mode activate)
  (my/set-buffer-mode (current-buffer) 'again))

我不确定将其挂接以影响新缓冲区的最佳位置。在这里,我使用buffer-list-update-hook,但是在更多情况下调用此调用的次数超出了我们的需要。

(add-hook 'buffer-list-update-hook
      '(lambda ()
         (my/set-buffer-mode (car (buffer-list)))))

上面的答案已修改为处理一些问题。特别是,我已回到使用,buffer-list-update-hook因为change-major-mode-hook未使用预期的当前缓冲区调用。记录下来,像@Dan在他的答案中那样建议开关缓冲区功能可能更有意义。
glucas 2014年

3

可以使用* scratch *缓冲区来创建与您正在处理的文件具有相同主模式的临时缓冲区。

这是一个emacs SE答案,可能会解决您的问题:

如何快速在文件和具有相同主模式的* scratch *缓冲区之间切换?

引用的问题和答案均由我发布。函数中的答案执行以下操作:

  • 如果您在文件的X大写模式下工作,则调用此函数将创建一个新的暂存缓冲区(*scratch-X-mode*如果尚不存在)将被调用,然后切换到该新创建的缓冲区。
  • 如果*scratch-X-mode*已经存在,它将简单地切换到该缓冲区。
  • 在该暂存缓冲区中再次调用此函数将使您返回到最初使用的文件缓冲区。

0

这里有一些很好的答案,但我想再添加一件事。Emacs具有大量功能,通常有几种方法可以执行某项操作。您可以在任何文件的顶部添加标签,这些标签告诉emacs不管扩展名是什么类型。例如添加以下内容:

# -*-Python-*-

即使没有.py扩展名,文件顶部也会让emacs知道它是Python文件。请注意,该#行的开头是Python样式的注释。对于不同的文件类型,可以使用不同的注释。例如,要指定一个Lisp文件,您可以使用;它开始注释行并在emacs中设置模式,如下所示:

; -*- mode: Lisp;-*-

请参见指定文件变量选择文件模式


是的,但是这里的问题是关于创建一个新的临时缓冲区(例如,使用switch-buffer)以及将模式自动设置为以外的其他内容fundamental-mode
glucas 2014年
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.