2012-09-22 17 views
3

在Emacs中使用Lisp函數來運行當前文件所對應的Java程序。如何在知道軟件包的同時調用java的Lisp函數?

(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稱爲java pkg.file從包含目錄PKG(其中file.java被放置在目錄的父目錄)的目錄。

如何修改函數以瞭解包並相應地構造參數爲java?我想人們可能會通過搜索包聲明當前文件解決這個問題,比如

package pkg; 

,如果找到一個它使用該套件名稱適當地調用java

回答

2

試試下面的代碼搜索當前文件的包聲明:

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

您可以使用此代碼來擴展您的功能像這樣:

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

謝謝。這似乎滿足了我的問題中的第一點。如果定義了'package',現在只剩下從當前目錄的父目錄(而不是當前)運行'java'的第二點。我閱讀了'shell-command'的文檔,但是我似乎無法找到如何影響shell啓動的目錄。 –

+0

啊,好的 - 我已經編輯了我的答案來解決第二部分。 – Thomas

+0

工程就像一個魅力。非常感謝! –

-1

要麼使用合適的Java IDE(最終如果您定期執行此操作),或者閱讀該文件以解析軟件包行。

另請注意,您將很可能還需要指定編譯根文件夾(或cd到它)以便能夠正確設置類路徑。

爲了派生實際的類名,讀取文件並搜索「package(。*);」 (匹配換行符)很可能會足夠好。坦率地說,當我需要這樣工作時,我寫了一個小腳本(在WIndows下的bat文件),它可以滿足我的需求。原因是我通常在類路徑上也需要大量的jar文件,最終歸結爲我需要指定整個命令行。

+4

如果他或她想堅持使用emacs,由於其他原因您可能不明白,他們究竟如何解析文件並在emacs lisp中獲得包行? – mwolfetech

+0

@mwolfetech我完全同情使用Emacs - 唯一的事情就是對於Java開發來說,更好的工具存在。我不熟悉Emacs-Lisp,但是閱讀文件並搜索「package(。*);」 (匹配換行符)可能是一個好方法。 –

相關問題