我使用一个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}}
答案 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约定。但同样,希望这足以让你开始。