如何使一个Lisp函数调用java同时知道包? [英] How to make a Lisp function call java while being aware of packages?

查看:250
本文介绍了如何使一个Lisp函数调用java同时知道包?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

 (defun java-run-current-file()
运行java程序当前文件对应于
(interactive)
(shell-command
(concatjava
(file-name-sans-extension
(file-name-nondirectory(buffer-file-name))))))

它可以通过剥离其路径和扩展名的当前文件名,并将其用作 java 的参数,这是从文件所在的路径运行。这种方法的问题是,如果当前文件是包的一部分,那么


  1. java 必须以包名称和一个点为前缀,

  2. java 必须从包含该包的目录。

所以例如,如果文件是file.java,包名是pkg 从包含目录pkg(放置file.java的目录的父目录)的目录中调用java 作为 java pkg.file



如何修改函数以了解包,并相应地将参数构造为 java 我想可以通过搜索当前文件来解决这个问题,例如

  PKG; 

如果发现它使用该包名称调用 java

解决方案

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

 (save-excursion 
(goto-char(point-min))
当(重新搜索转发^ \\s * package\\\s + \\(。* \\);(point-max)t)
(match-字符串1)))

这将返回一个声明和分号。如果没有发现这样的声明,它将返回 nil



(请注意,如果有评论,可能会失败在一个C风格的多行注释( / * ... * / )中,在实际包声明之前的某个地方声明了 package code>))



为了更改运行shell命令的目录,请使用 cd 函数。因为在Java中,包结构应该反映目录结构,可以使用上面的代码确定的包信息来找出你的源代码的基本目录:

 (let((directory(file-name-directory(buffer-file-name)))
(sub-dirs(reverse(split-string package \\。))))
(而sub-dirs
(if(string-match(concat^ \\(。* / \\)(regexp -cote(car sub-dirs))/ $)目录)
(setq目录(match-string 1目录)
sub-dirs(cdr sub-dirs))
包不匹配目录结构)))
(cd目录))

你可以使用这个代码来扩展你的函数,如下所示:

 (defun java-run-current- file()
运行当前文件对应的java程序
(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 )$)

(如果目录
(setq目录(文件truename目录))
(错误当前缓冲区未访问文件))

(当包
(setq sub-dirs(reverse(split-string package\\。)))

(while sub-dirs
(if(string-match(concat^ \\(。* / \\)(regexp-quote(car sub-dirs))/ $)directory)
(setq目录(match-string 1目录)
sub-dirs(cdr sub-dirs))
(错误包不匹配目录结构))))

(cd目录)
(shell命令
(conca tjava
(如果包(concat package。))
(file-name-sans-extension
(file-name-nondirectory(buffer-file-name) ))))))


In Emacs use a Lisp function to run the Java program the current file correspond to.

(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. 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
  2. java has to be run from the directory containing the package.

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

How can I modify the function to be aware of packages and construct the argument to java accordingly? 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.

解决方案

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. It will return nil if no such declaration is found.

(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 (/* ... */).)

In order to change the directory from which a shell command is run, use the cd function. 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:

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

这篇关于如何使一个Lisp函数调用java同时知道包?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆