简体   繁体   English

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

[英]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 这种方法的问题是如果当前文件是包的一部分那么

  1. the argument to java has to be prefixed with the package name and a dot, and java的参数必须以包名和点为前缀,并且
  2. 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM