定义 Java 类的文件可以通过声明它们属于特定包来组织成包,例如
package foo.bar;
它声明有问题的文件属于 package 的子bar
包foo
。然后将文件存储在具有与包的层次结构相对应的层次结构的目录中。此外,包层次结构的根通常是某个目录src
。是否可以编写一个扩展为包声明的 YASnippet,以便从当前文件的路径中获取包名?
您可以使用嵌入式 Emacs Lisp 编写一个片段,该片段获取缓冲区的路径并将其转换为包名称,方法是将目录 src 视为包层次结构中的根:
# -*- mode: snippet -*-
#name : package
#key : pa
# --
package ${1:`(mapconcat 'identity (cdr (member "src" (split-string default-directory "/" t))) ".")`};$0
这将识别多级包层次结构,即,如果您正在编辑的文件的缓冲区路径是 /home/nn/src/foo/bar/Baz.java,则片段将扩展为
package foo.bar;
请注意,这需要您使用 src 作为存储包层次结构的根目录。如果缓冲区的路径中有名为 src 的目录,则片段将扩展为
package ;
要让代码片段将某个其他目录识别为包层次结构中的根目录,只需替换"src"
为所需的目录名称即可。
这是我尝试 Java 时的设置:
# -*- mode: snippet -*-
# name: package
# key: pa
# --
`(insert (concat "package " (java-package-name (buffer-file-name)) ";\n"))`
上面的函数定义为:
(defun java-package-name (file)
"Generates package name for FILE, based on path."
(let* ((f (file-name-directory file))
(rem
(car
(sort
(delq nil
(mapcar
(lambda(x)
(and (string-match (expand-file-name x) f)
(substring f (match-end 0))))
(parse-colon-path (getenv "CLASSPATH"))))
(lambda (a b) (< (length a) (length b)))))))
(cond
((null rem)
"Not on CLASSPATH.")
((= 0 (length rem))
"At root of CLASSPATH")
(t
(mapconcat
#'downcase
(delete "" (split-string rem "[\\\\/]"))
".")))))
它会检查您是否CLASSPATH
正在寻找最短的包名称。