find-file-noselect`有什么问题?


11

在最近的答案lunaryorn,他说:

但是,出于评论中已经提到的原因,我建议不要使用Org的其他大部分内容:它很旧,并且充满了遗留和有害的做法(例如,find-file-noselect以非交互方式读取文件)。

谁能解释为什么find-file-noselect在Elisp程序中读取文件不是一个好主意吗?有没有更好的办法?我问是因为我正在考虑在我的一个项目中使用它。


似乎以前没有good-practices标签。使用它是一个好主意吗?
mbork

我认为那good-practices应该属于SE 所不赞成的“元标记”类别。
nispio 2014年

1
@nispio我认为这是一个有效的标记,但是我们可以将其带到meta中。
马拉巴巴

1
@nsipio:我浏览了这篇文章,但我不同意。但是决定的不是我。;-)
mbork 2014年

Answers:


14

TL; DR:由于find-file-noselect无法控制实际发生的情况,最终可能会在缓冲区中启用任意次要模式,具体取决于用户在中启用了什么init.el。此外,清理工作很困难。

使用with-temp-bufferinsert-file-contents代替。如果您在缓冲区中需要特定的主要或次要模式,请显式启用它们。要写入文件,请改用with-temp-file(尽管其名称),但您可以写入任意文件。

副作用

find-file-noselect很多副作用,包括

  • 互动式提问(仅在非互动式使用中是不可以的),
  • 自动为只读文件启用查看模式,
  • 否则进入正常模式,
  • 和运行find-file-hook

普通模式本身

  • 自动为当前缓冲区选择适当的主模式,
  • 运行所有相应的主要和次要模式挂钩,
  • 并读取当前缓冲区的所有局部变量,即文件变量和目录变量,它们又可能会询问有关不安全局部变量的交互问题。

由于所有钩子均已运行,因此您会获得用户在其中启用的所有次要模式和钩子功能init.el,这可能会导致各种情况,从次要不便(如果启用了不希望的次要模式)到重大破坏(如果用户添加了一个预期会导致不便的钩子功能)从交互式上下文中调用)。

有关示例,请参见https://github.com/flycheck/flycheck/issues/366。使用find-file-noselect导致数据文件由Flycheck进行语法检查,并且由于它是在Emacs关闭时发生的,因此没有时间再次进行适当清理,从而留下了临时文件。

清理

有了find-file-noselect你需要格外小心再次杀缓冲区。 find-file-noselect不会为您做到这一点。

您需要记住某个地方的缓冲区,并谨慎使用unwind-protect以确保即使在非本地退出的情况下缓冲区也被杀死。

备择方案

要读取文件,请使用with-temp-bufferinsert-file-contents,它只做最基本的事情,例如编码系统转换,但不问问题,启用钩子或设置局部变量:

(with-temp-buffer
  (insert-file-contents (locate-user-emacs-file "foo.el"))
  ;; Enter the major mode explicitly
  (emacs-lisp-mode)
  ;; …
  )

with-temp-buffer 请注意适当地杀死其主体末端的临时缓冲区。

要写入文件,请使用with-temp-file,它会创建一个临时缓冲区,并将内容写入文件体末尾的给定文件名:

(with-temp-file  (locate-user-emacs-file "foo.el")
  (prin1 (list 'my 'data) (current-buffer)))

10

根据Elisp手册的24.3节:

要将文件的内容复制到缓冲区中,请使用函数 insert-file-contents。(不要insert-file在Lisp程序中使用该命令,因为那样会设置标记。)

在Elisp文档中搜索find-file-noselect很明显,它所做的不仅仅是将文件读入缓冲区。也许认为使用此功能不是一个好主意的人正在考虑可能有害的副作用?我想这取决于您要实现的目标。如果您想拥有尽可能干净/原始的缓冲区内容,则最好使用旧的和可信赖的with-temp-buffer+ insert-file-contents组合。如果你想在缓冲区的内容要尽可能接近到什么find-file产生,也许你想用find-file-noselect?也许他正在考虑find-file;)


3
如果某些事情是非交互地完成的,那么我看不到任何您希望“缓冲区内容与find-file产生的内容接近”的情况。find-file很慢,因为它执行了大量不必要的操作,包括各种钩子。您可能需要查找文件的唯一“功能”是主模式,但是您应该自己激活它(您甚至不能保证查找文件始终会打开您想要的模式)。
马拉巴巴2014年

马拉巴巴(Malabarba):如果您打算让缓冲区保持可供用户编辑,那么您很可能希望模仿该find-file过程。
菲尔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.