如何使用 Emacs Lisp 检查文件是不是存在?

Posted

技术标签:

【中文标题】如何使用 Emacs Lisp 检查文件是不是存在?【英文标题】:How can I check if a file exists using Emacs Lisp?如何使用 Emacs Lisp 检查文件是否存在? 【发布时间】:2010-10-30 22:26:24 【问题描述】:

我希望 emacs 将打开时生成的文件标记为只读。我缺少的部分难题是如何检查文件是否“存在”。我目前有以下:

;;
;; get file extension
;;
(defun get-ext (file-name)
  (car (cdr (split-string file-name "\\."))))

;; 
;; get the base name of the file
;;
(defun base-name (file-name)
  (car (split-string file-name "\\.")))

;;
;; if an 'lzz' file exists for this header, mark it as read only
;;
(defun mark-read-only ()
  (if (string= (get-ext (cur-file)) "h")
      (if ( ??file-exists??? (concat (base-name (cur-file)) ".lzz") )
          (toggle-read-only))))

“???file-exists???”可以使用什么?

一旦我找到这个,我会将“mark-read-only”添加到适当的钩子(我认为是 find-file-hook)。

背景

我们使用lzz 作为代码生成器来简化我们的 C/C++ 开发过程。简而言之,lzz 采用单个输入文件(看起来很像 C/C++)并根据需要生成头文件和源文件。

默认情况下,lzz 包含#line 指令,以便调试器指向原始源代码而不是生成的源代码,但是,为了减少编译依赖性,我们通常在头文件中禁用这些指令。结果是在调试模板或内联函数时,调试器一般指向的是生成的头文件,而不是原来的源文件。

这没什么大不了的,但是,最近我发现在调试时我会快速修改显示的文件,然后我会重新构建。当然,这通常意味着我所做的更改会消失,因为我编辑的文件是生成的,因此在库重建期间这些更改会被“吹走”。

解决方案

感谢大家的帮助和cmets。特别感谢cobbal 指出要使用的正确函数。

这是生成的代码(也基于此处的其他 cmets 进行了更新):

(defun cur-file ()
  "Return the filename (without directory) of the current buffer"
  (file-name-nondirectory (buffer-file-name (current-buffer)))
  )

(defun mark-generated-as-read-only ()
  "Mark generated source files as read only.
Mark generated files (lzz or gz) read only to avoid accidental updates."
  (if
      (or (string= (file-name-extension (cur-file)) "h")
          (string= (file-name-extension (cur-file)) "cpp"))
      (cond
       (
        (file-exists-p (concat (file-name-sans-extension (cur-file)) ".lzz"))
        (toggle-read-only))
       (
        (file-exists-p (concat (file-name-sans-extension (cur-file)) ".gz") )
        (toggle-read-only))
       )
    )
  )

【问题讨论】:

不用将 cmets 放在函数之上,在 Elisp 中,您可以将它们写在函数声明的第一行。它称为“文档字符串”。见gnu.org/software/emacs/elisp/html_node/… 注意:你的前两个函数是 Emacs 自带的,它们被命名为 'file-name-extension 和 'file-name-sans-extension 【参考方案1】:

试试file-exists-p

“如果文件filename存在则返回t(你是否可以读取它。)”。

请注意,它并不适用于文件,也适用于目录。

【讨论】:

为什么我用“C-H a”appros 搜索这个功能没有出现?我尝试搜索文件并查看“存在”的结果,但根本没有匹配项! file-exists-p 不会出现在“C-H a”下,因为它不是“交互式”功能。它应该显示在“M-x apropos”下。 这正是我在 .emacs 中有这个的原因(define-key help-map "a" 'apropos)这样,“C-h a”会为我查找所有符号。 是的,它叫file-directory-p @Trey 也可以将apropos-do-all设置为非nil来获取apropos-command(默认“C-h a”绑定)来搜索非交互函数【参考方案2】:

根据您的需要,您可能需要file-readable-p 而不是file-exists-p

Apropos 只能帮您到此为止。 Icicles 提供了apropos completion 和progressive completion,让您可以轻松找到以任意顺序匹配子部分的命令、函数、变量等名称的帮助(是file-exists-p 还是exists-file-p?)。

【讨论】:

【参考方案3】:

使用f.el,用于文件和目录操作的现代库。您可以使用f-exists?f-file?f-directory? 和许多其他谓词。该库比标准函数更好,因为它是您在一个命名空间下需要的所有与文件相关的函数。

【讨论】:

很好,但是这些函数名不遵循标准的 lisp 约定 (...-p)

以上是关于如何使用 Emacs Lisp 检查文件是不是存在?的主要内容,如果未能解决你的问题,请参考以下文章

如何检查 Emacs 中是不是存在当前缓冲区?

如何调试 elisp?

如何在 Emacs Lisp 中进行闭包?

Emacs我想从lisp函数调用execute-kbd-macro

emacs lisp

Common Lisp 入门配置开发环境 in Emacs