[英]How to make a Lisp function call java while being aware of packages?
In Emacs use a Lisp function to run the Java program the current file correspond to. 在Emacs中使用Lisp函数来运行当前文件对应的Java程序。
(defun java-run-current-file ()
"Runs the java program the current file correspond to"
(interactive)
(shell-command
(concat "java "
(file-name-sans-extension
(file-name-nondirectory (buffer-file-name))))))
It works by stripping the current file name of its path and extension and using it as an argument to java
which is run from the path where the file is at. 它的工作原理是剥离其路径和扩展名的当前文件名,并将其用作
java
的参数,该文件位于文件所在的路径上。 The problem with this approach is that if the current file is part of a package then 这种方法的问题是如果当前文件是包的一部分那么
java
has to be prefixed with the package name and a dot, and java
的参数必须以包名和点为前缀,并且 java
has to be run from the directory containing the package. java
。 So for example if the file is file.java and the package name is pkg java
is called as java pkg.file
from the directory containing the directory pkg (the parent directory of the directory where file.java is placed). 因此,例如,如果该文件是file.java和包名是PKG
java
称为java pkg.file
从包含目录PKG(其中file.java被放置在目录的父目录)的目录。
How can I modify the function to be aware of packages and construct the argument to java
accordingly? 如何修改函数以了解包并相应地构造
java
的参数? I guess one might solve this by searching the current file for a package declaration, such as 我想有人可以通过在当前文件中搜索包声明来解决这个问题,例如
package pkg;
and if it finds one it uses that package name to call java
appropriately. 如果找到一个,它使用该包名称来适当地调用
java
。
Try the following code to search the current file for a package declaration: 请尝试以下代码在当前文件中搜索包声明:
(save-excursion
(goto-char (point-min))
(when (re-search-forward "^\\s *package\\s +\\(.*\\);" (point-max) t)
(match-string 1)))
This will return the value between a package
declaration and the semi-colon. 这将返回
package
声明和分号之间的值。 It will return nil
if no such declaration is found. 如果没有找到这样的声明,它将返回
nil
。
(Beware that this might fail if there is a commented-out package
declaration somewhere before the actual package declaration, in a C-style, multi-line comment ( /* ... */
).) (请注意,如果在实际的包声明之前某处有一个注释掉的
package
声明,则可能会失败,在C风格的多行注释( /* ... */
)中。)
In order to change the directory from which a shell command is run, use the cd
function. 要更改运行shell命令的目录,请使用
cd
函数。 Since in Java the package structure should reflect the directory structure, you can use the package information determined by the above code to figure out the base directory of your source code: 由于在Java中包结构应该反映目录结构,您可以使用上面代码确定的包信息来确定源代码的基本目录:
(let ((directory (file-name-directory (buffer-file-name)))
(sub-dirs (reverse (split-string package "\\."))))
(while sub-dirs
(if (string-match (concat "^\\(.*/\\)" (regexp-quote (car sub-dirs)) "/$") directory)
(setq directory (match-string 1 directory)
sub-dirs (cdr sub-dirs))
(error "Package does not match directory structure")))
(cd directory))
You may use this code to extend your function like so: 您可以使用此代码来扩展您的功能,如下所示:
(defun java-run-current-file ()
"Runs the java program the current file corresponds to"
(interactive)
(let* ((package (save-excursion
(goto-char (point-min))
(when (re-search-forward "^\\s *package\\s +\\(.*\\);" (point-max) t)
(match-string 1))))
(directory (file-name-directory (buffer-file-name)))
sub-dirs)
(if directory
(setq directory (file-truename directory))
(error "Current buffer is not visiting a file"))
(when package
(setq sub-dirs (reverse (split-string package "\\.")))
(while sub-dirs
(if (string-match (concat "^\\(.*/\\)" (regexp-quote (car sub-dirs)) "/$") directory)
(setq directory (match-string 1 directory)
sub-dirs (cdr sub-dirs))
(error "Package does not match directory structure"))))
(cd directory)
(shell-command
(concat "java "
(if package (concat package ".") "")
(file-name-sans-extension
(file-name-nondirectory (buffer-file-name)))))))
Either use a proper Java IDE (you will eventually if you do this on a regular basis) or read the file to parse the package line. 使用适当的Java IDE(如果定期执行此操作,最终将使用)或读取文件以解析包行。
Also note that you will most likely also need to specify the compilation root folder (or cd to it) to be able to set the class path properly. 另请注意,您很可能还需要指定编译根文件夹(或cd到它)才能正确设置类路径。
For deriving the actual class name, reading the file and searching for "package (.*);" 用于派生实际的类名,读取文件并搜索“package(。*);” (matching newlines too) would most likely be good enough.
(匹配换行)也很可能足够好。
To be frank, when I need to work like this, I write a small script (bat-file under WIndows) which does what I need. 坦率地说,当我需要像这样工作时,我会编写一个小脚本(在WIndows下的bat文件),它可以满足我的需求。 The reason is that I usually need a lot of jarfiles on the classpath too, which eventually boils down to me needing to specify the whole command line anyway.
原因是我通常在类路径上也需要很多jar文件,这最终归结为我需要指定整个命令行。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.