如何避免在Emacs中弹出* Async Sh​​ell Command *缓冲区?

时间:2012-12-16 13:52:55

标签: emacs asynchronous dired

我的~/.emacs包含以下设置,用于打开某些应用程序的某些文件(Ubuntu 12.10; Emacs 24):

(setq dired-guess-shell-alist-user
      '(("\\.pdf\\'" "okular ? &")
    ("\\.djvu\\'" "okular ? &")
        ("\\.mp3\\'" "vlc ? &")
    ("\\.mp4\\'" "vlc ? &")
    ))

当我导航到dired-mode中的.pdf并点击!时,它会打开Okular中的.pdf,但是直接缓冲区分为两部分,第二部分现在是无用的包含

等内容的*Async Shell Command*缓冲区
okular(25393)/kdecore (KConfigSkeleton) KCoreConfigSkeleton::writeConfig:
okular(25393)/kdecore (KConfigSkeleton) KCoreConfigSkeleton::writeConfig:
okular(25393)/kdecore (KConfigSkeleton) KCoreConfigSkeleton::writeConfig:
okular(25393)/kdecore (KConfigSkeleton) KCoreConfigSkeleton::writeConfig:

如何防止此缓冲区被打开? (除非,如果有错误,此信息有用)。

我发现了相关问题herehere,但它们似乎只是处理异步执行的特定命令,而不是一般*Async Shell Command*(如果可能,我想更改异步进程的一般行为,不仅适用于某些文件类型)

8 个答案:

答案 0 :(得分:14)

找到此here

(call-process-shell-command "okular&" nil 0)

适合我。没有stderr gobbledygook。

答案 1 :(得分:5)

问题是在2012年提出的,在我写作时,最近的答案是2015年。现在,2017年,我可以说答案很简单:

(add-to-list 'display-buffer-alist (cons "\\*Async Shell Command\\*.*" (cons #'display-buffer-no-window nil)))

答案 2 :(得分:3)

我正在回顾用户1404316的回答,但这是另一种达到预期结果的通用方法。

(defun async-shell-command-no-window
    (command)
  (interactive)
  (let
      ((display-buffer-alist
        (list
         (cons
          "\\*Async Shell Command\\*.*"
          (cons #'display-buffer-no-window nil)))))
    (async-shell-command
     command)))

答案 3 :(得分:2)

遗憾的是,没有好办法避免这个缓冲区,因为它是由'shell-command'函数直接调用的('async-shell-command'只是一个包装器)。

因此,更好的方法是将'async-shell-command'替换为'start-process'。 您应该使用“set-process-sentinel”开始处理以检测进程发出“退出信号”的时刻。然后杀死进程。

答案 4 :(得分:1)

我不完全确定通常会为异步进程执行此操作,但对于通过async-shell-command的任何内容,这应该可以正常工作:

    (defadvice async-shell-command (around hide-async-windows activate)
       (save-window-excursion
          ad-do-it))

答案 5 :(得分:0)

稍微复杂的咒语应该能让你得到你想要的东西。只需使用shell命令,例如:(okular ? >& /dev/null &)

我没有用okular测试过这个,但是我可以做 M - ! ((echo foo; sleep 10; echo bar) >& /dev/null &)并且Emacs立即返回而不创建新的缓冲区。

答案 6 :(得分:0)

我使用这种方法解决了这个问题:

;list of programs, corresponding to extensions
(setq alist-programs
      '(("pdf" ."okular")
        ("djvu" . "okular")
        ("mp3" . "xmms")))

(defun my-run-async-command (command file)
  "Run a command COMMAND on the file asynchronously.
   No buffers are created"
  (interactive
   (let ((file (car (dired-get-marked-files t current-prefix-arg))))
     (list
      ;last element of alist-programs, contains COMMAND
      (cdr
       (assoc
        (file-name-extension file)
        alist-programs))
      file)))
  ;begin of function body
  (if command ;command if not nil?
      (start-process "command" nil command file)
    )
)

;attach function to <f2> key
(add-hook 'dired-mode-hook
      (lambda ()
    (define-key dired-mode-map (kbd "<f2>") 'my-run-async-command)))

答案 7 :(得分:0)

如果他在路径上运行不同的程序,则使用启动过程的建议是可以的。但是,如果您想在特定目录(例如,项目目录)中运行一些Shell命令,则只需平息弹出窗口-您经常需要缓冲区,但只是不想让它突然跳起来。例如,我运行一个网络服务器,我想查看输出,只是现在不行...

  (use-package php-mode
    :config
    (add-to-list 'display-buffer-alist
    (cons "\\*Symfony Web Server\\*.*" (cons #'display-buffer-no-window nil)))
    (defun php-mode-webserver-hook ()
      (if (projectile-project-root) (let ((default-directory (projectile-project-root)))
        (unless (get-buffer "*Symfony Web Server*" )
          (async-shell-command "bin/console server:run" "*Symfony Web Server*")))))
    :hook (php-mode . php-mode-webserver-hook))