如何编写根据缓冲区的目录扩展到 Java 包声明的 YASnippet ?



可以通过声明属于特定软件包来组织定义Java类的文件,例如

package foo.bar;

宣布所讨论的文件属于软件包foo的子包bar。然后将文件存储在目录中,层次结构与软件包的层次结构相对应。同样,软件包层次结构的根通常是一些目录src。是否可以编写Yasnippet扩展到软件包声明中,以便从当前文件的路径中获取软件包名称?

您可以用嵌入式emacs lisp编写摘要,该片段通过将目录src视为软件包层次结构中的root:

来获取缓冲区的路径并将其转换为软件包名称:
# -*- mode: snippet -*-
#name : package
#key : pa
# --
package ${1:`(mapconcat 'identity (cdr (member "src" (split-string default-directory "/" t))) ".")`};$0

这将识别多级软件包层次结构,即,如果您要编辑的文件的缓冲区的路径为/home/nn/src/foo/bar/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寻找最短的软件包名称。