如何模块化处理Ja​​va文件的两个Lisp函数的通用功能?

时间:2012-10-15 08:48:44

标签: java emacs elisp

我使用一个Lisp函数编译当前的Java文件,另一个运行它。这两个函数使用相同的功能来获取程序包名称和编译/运行的相应目录(此功能已发布为an answer to another question)。我想模块化这些函数的通用功能,即从(let*(cd但不包括cd。我怎么能这样做?

作为奖励,我想撤消更改目录(C-x C-f:ing),因为这些功能是为了避免意外行为,例如从parten目录中查找文件((add-hook 'java-mode-hook (lambda () (defun java-compile-current-file () "Compiles the current file with javac" (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) (compile (concat "javac -Xlint:all " ; Tog bort -Werror från ; argumenten. För ; gnälligt! (if package (concat package "/") "") (file-name-nondirectory (buffer-file-name)))))) (local-set-key [(f8)] 'java-compile-current-file) ;; https://stackoverflow.com/a/12548762/789593 (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))))))) (local-set-key [(f7)] 'java-run-current-file))) )。它一直是suggested that this can be achieved by unwind-protect

{{1}}

1 个答案:

答案 0 :(得分:1)

这是一个粗略的,未经测试的代码重构。它不是特别优雅或惯用,但至少应该足以让你开始。

;; 1. Refactored `java-get-package' into its own `defun'
;; 2. Refactored `java-package-directory' into its own `defun'
;; 3. Broke out `defun's outside of `java-mode-hook'
;; 4. Use (let ((default-directory ...) ...) instead of (cd ...) (...)
;; 5. Broke out keystroke assignments into `my-java-mode-hook'

(defun java-get-package ()
  "Get package definition before point"
  (interactive)
  (save-excursion
    (save-match-data  ;; Added; you want this too
      (goto-char (point-min))
      (when (re-search-forward "^\\s *package\\s +\\(.*\\);"
                               (point-max) t)
        (match-string 1)) )) )

(defun java-package-directory (package)
  "Get package directory of PACKAGE in current buffer"
  (let ((directory (file-name-directory (buffer-file-name)))
        sub-dirs)
    (if directory
        (setq directory (file-truename directory))
      (error "Current buffer is not visiting a file"))
    (save-match-data
      (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") ) ) )
    directory) )

(defun java-compile-current-file ()
 "Compiles the current file with javac"
 (interactive)
 (let* ((package (java-get-package))
        (default-directory (java-package-directory package)) )
   (compile
    (concat "javac -Xlint:all " ; Removed too noisy -Werror
        (if package (concat package "/") "")
        (file-name-nondirectory (buffer-file-name)) ) ) ))

(defun java-run-current-file ()
 "Runs the java program the current file corresponds to"
 (interactive)
 (let* ((package (java-get-package))
        (default-directory (java-package-directory package)) )
   (shell-command
    (concat "java "
        (if package (concat package ".") "")
        (file-name-sans-extension
         (file-name-nondirectory (buffer-file-name)) ) )) ))

(defun my-java-mode-hook () "Stuff to run when entering Java mode"
    (local-set-key [(f7)] 'java-run-current-file)
    (local-set-key [(f8)] 'java-compile-current-file) )

(add-hook 'java-mode-hook #'my-java-mode-hook)

新函数应该接受一个缓冲区参数,以便您可以在不同于您所在缓冲区的缓冲区上调用它们,以实现一般可用性和遵守常见的Emacs约定。但同样,希望这足以让你开始。