2012-10-15 1 views
1

하나의 Lisp 함수를 사용하여 현재 Java 파일을 컴파일하고 다른 하나는이를 실행합니다. 두 함수 모두 동일한 기능을 사용하여 패키지 이름과 적절한 디렉토리를 컴파일/실행합니다 (이 기능은 an answer to another question으로 게시 됨). 이 기능의 일반적인 기능을 모듈화하고 싶습니다. 예를 들어 (let*에서 (cd까지 포함하고 싶습니다. 어떻게해야합니까?Java 파일을 처리하는 두 개의 Lisp 함수의 공통 기능을 모듈화하는 방법은 무엇입니까?

보너스 나는 parten 디렉토리에서 시작하는 파일 (C-x C-f) 찾기와 같은 예기치 않은 동작을 방지하기 위해 디렉토리 변경 (cd : ing)을 실행 취소하고 싶습니다. 그것은 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))) 
+1

'(defun ...)'을 java-mode-hook에 추가하면,'java-compile-current-file'을 같은 것으로 지정 (다시)한다는 의미입니다. .java 파일을 방문 할 때마다 아마 당신이 원하는 것이 아닙니다. – Thomas

+0

@ 토마스 나는'defun'을하기 위해 ['eval-after-load'] (http://stackoverflow.com/a/2736153/789593)와 함께 가야합니까? –

+0

@wvxvw 괄호 문제를 해결했다고 생각합니다. 후크와 모드 맵에서 머리를 주셔서 감사합니다. '(define-key java-mode-map 'java-run-current-file)'? 'compile'에 관해서는'java-compile-current-file'의 뒷부분을 공부하면 알 수 있듯이 이미 사용하고 있습니다. 마지막으로 Java와 Emacs에서 SCons를 사용하기위한 좋은 참고 자료를 얻었습니까? –

답변

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) 

새로운 기능은 아마 버퍼 인수를 받아 들여야한다. 그러나 다시 한번, 이것이 당신을 시작할 수 있기를 바랍니다.

+0

내가 추가 한 HTML 주석은 구문 강조를 제어합니다 (http://meta.stackexchange.com/a/75019/163868). 기본 비교보기는 그러한 주석 추가 표시에 좋지 않습니다. 더 나은보기를 위해 diff 행보기 "세로 막대에있는 세 번째 아이콘"과 나란히 "마크 업 소스 차이점을 나란히 표시합니다."를 참조하십시오. –

+0

상당한 추가 리팩터링을 수행했는지 여부. 위의 내 의견 중 일부를 제거하고 일부는 귀하의 것으로 표시합니다. – tripleee

+0

side-by-side diff 링크에 대한 포인터를 보내 주셔서 감사합니다! – tripleee

관련 문제