如何让Lisp函数在知道包时调用java?

在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)))))) 

它的工作原理是剥离其路径和扩展名的当前文件名,并将其用作java的参数,该文件位于文件所在的路径上。 这种方法的问题是如果当前文件是包的一部分那么

  1. java的参数必须以包名和点为前缀,并且
  2. 必须从包含该包的目录运行java

因此,例如,如果文件是file.java且包名称是pkg, java pkg.file包含目录pkg(放置file.java的目录的父目录)的目录中将java调用为java pkg.file

如何修改函数以了解包并相应地构造java的参数? 我想有人可以通过在当前文件中搜索包声明来解决这个问题,例如

 package pkg; 

如果它找到一个,它使用该包名称来适当地调用java

请尝试以下代码在当前文件中搜索包声明:

 (save-excursion (goto-char (point-min)) (when (re-search-forward "^\\s *package\\s +\\(.*\\);" (point-max) t) (match-string 1))) 

这将返回package声明和分号之间的值。 如果没有找到这样的声明,它将返回nil

(请注意,如果在实际的包声明之前某处有一个注释掉的package声明,则可能会失败,在C风格的多行注释( /* ... */ )中。)

要更改运行shell命令的目录,请使用cd函数。 由于在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)) 

您可以使用此代码来扩展您的function,如下所示:

 (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))))))) 

使用适当的Java IDE(如果定期执行此操作,最终将使用)或读取文件以解析包行。

另请注意,您很可能还需要指定编译根文件夹(或cd到它)才能正确设置类路径。

为了获得实际的类名,读取文件并搜索“package(。*);” (匹配换行)也很可能足够好。

坦率地说,当我需要像这样工作时,我会写一个小脚本(在WIndows下的bat文件),它可以满足我的需要。 原因是我通常在类路径上也需要很多jar文件,这最终归结为我需要指定整个命令行。