如何模块化两个处理Java文件的Lisp函数的常用功能? [英] How to modularize the common functionality of two Lisp functions handling Java files?

查看:127
本文介绍了如何模块化两个处理Java文件的Lisp函数的常用功能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用一个Lisp函数来编译当前的Java文件,另一个用于运行它。这两个函数都使用相同的功能来获取包名称和编译/运行的相应目录(此功能已发布为其他答案问题)。我想模块化这些函数的常用功能,即从(let * 到但不包括(cd )。如何做到这一点?

I use one Lisp function to compile the current Java file and another to run it. Both functions use the same functionality to get the package name and the appropriate directory to compile/run from (this functionality was posted as an answer to another question). I would like to modularize the common functionality of these functions, i.e. from (let* to but not including (cd. How can I do this?

作为奖励我想撤销目录的更改( cd )作为函数,以避免出现意外的行为,例如从parten目录中查找文件( Cx Cf ),它已经是建议这可以通过解除保护

As bonus I would like to undo the changing of directory (the cd:ing) as the functions are done to avoid unexpected behaviour such as finding files (C-x C-f) starting in the parten directory. It has been suggested that this can be achieved by unwind-protect.

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


推荐答案

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

Here is a crude, untested, refactoring of the code. It's not particularly elegant or idiomatic, but should at least be enough to get you started.

;; 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公约。但再次希望这足以让您开始。

The new functions should probably accept a buffer argument so that you can call them on a different buffer than the one you're in, for general usability and adherence to common Emacs conventions. But again, hope this is enough to get you started.

这篇关于如何模块化两个处理Java文件的Lisp函数的常用功能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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