How do I write a YASnippet that expands into a Java package declaration according to the buffer's directory?

StackOverflow https://stackoverflow.com/questions/13000278

  •  13-07-2021
  •  | 
  •  

Question

Files that define Java classes can be organized into packages by declaring them to belong to particular package, e.g.

package foo.bar;

which declares that the file in question belongs to the subpackage bar of the package foo. The files are then stored in directories with a hierarchy corresponding to the hierarchy of the packages. Also, the root of the package hierarchy is usually some directory src. Is it possible to write a YASnippet that expands into a package declaration such it gets the package name from the path of the current file?

Was it helpful?

Solution

You can write a snippet with embedded Emacs Lisp that gets the buffer's path and converts it to a package name by treating the directory src as the root in the package hierarchy:

# -*- mode: snippet -*-
#name : package
#key : pa
# --
package ${1:`(mapconcat 'identity (cdr (member "src" (split-string default-directory "/" t))) ".")`};$0

This will recognize multi-level package hierarchies, i.e. if the path to the buffer of the file you are editing is /home/nn/src/foo/bar/Baz.java the snippet will expand to

package foo.bar;

Note that this requires you to use src as the root directory storing the package hierarchy. If there is directory named src in the path to the buffer the snippet will expand to

package ;

To have the snippet recognize some other directory as the root in the package hierarchy simply replace "src" with the desired directory name.

OTHER TIPS

This was my setup when I was trying out Java:

# -*- mode: snippet -*-
# name: package
# key: pa
# --
`(insert (concat "package " (java-package-name (buffer-file-name)) ";\n"))`

And the function from above is defined as:

(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 "[\\\\/]"))
       ".")))))

It checks your CLASSPATH looking for shortest package name.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top