【问题标题】:How to avoid pop-up of *Async Shell Command* buffer in Emacs?如何避免在 Emacs 中弹出 *Async Sh​​ell Command* 缓冲区?
【发布时间】:2012-12-16 13:52:54
【问题描述】:

我的~/.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,但 dired-buffer 分为两部分,第二部分现在是无用的 *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*(如果可能,我想更改异步进程的一般行为,不仅适用于某些文件类型)

【问题讨论】:

  • 看看.../lisp/simple.el源代码中的实际函数——即defun shell-commanddefun async-shell-command。您甚至可以创建自己的自定义函数和/或使用defalias。当使用start-process 时,第二个参数是输出缓冲区名称——使用nil 作为第二个参数可以防止创建输出缓冲区。您可以将set-process-sentinelstart-process 结合使用。
  • async-shell-command 的文档字符串声明:... In Elisp, you will often be better served by calling 'start-process' directly, since it offers more control and does not impose the use of a shell (with its need to quote arguments).

标签: emacs asynchronous dired


【解决方案1】:

找到这个here

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

为我工作。没有标准错误 gobbledygook。

【讨论】:

  • 实际上,这是唯一真正有效的答案:没有消息日志,也没有奇怪的弹出窗口。
  • 谁能详细说明一下?我要把这个函数放在dired-guess-shell-alist-user 里面吗?如何?我刚刚试过:(add-to-list 'dired-guess-shell-alist-user '("\\.pdf$" (call-process-shell-command "evince" nil 0))),但它不起作用 - 它打开了 evince,但没有打开当前的文件。
【解决方案2】:

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

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

【讨论】:

  • 这仍然会创建一个缓冲区,但至少它不会突然出现并占据屏幕的一半。我坚持这个,这是最简单的解决方案。
【解决方案3】:

我捎带了 user1404316 的回答,但这是实现预期结果的另一种通用方法。

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

【讨论】:

  • 这是最简单的答案!仅针对特定命令避免缓冲区。用它来编写创建 TAGS 文件 (defun mktags-here () (interactive) ... (async-shell-command (message (format "ctags -e -R .")))) 的命令。
  • call-process-shell-command 并在命令中添加 & 对我来说是最简单的。
【解决方案4】:

我不完全确定是否对一般异步进程执行此操作,但对于通过async-shell-command 的任何操作,这应该可以:

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

【讨论】:

  • 但是你正在强制所有使用 async-shell-command 丢失缓冲区。我认为那将是矫枉过正。在某些情况下,您确实希望看到输出。更改通知以添加指定是否执行 save-window-excursion 的参数应该不会太难,但是为什么要首先使用通知;改用简单的包装函数。
  • ...我确实意识到 OP 特别要求修复async-shell-command,但应该强调与它混淆的警告。
  • 这对我不起作用。我仍然得到 Async Sh​​ell 命令缓冲区。
  • 那是因为async-shell-command 调用shell-command 来发挥它的魔力。
【解决方案5】:

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

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

【讨论】:

  • start-process 根本不同,因为您不能传递在当前目录的上下文中执行的 SHELL 命令。
【解决方案6】:

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

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

【讨论】:

  • 不错。但是,Async Sh​​ell Command 缓冲区仍然会弹出(现在只是空的)。如果我尝试你的M-! ... 命令,我会得到“shell 命令成功,没有输出”
【解决方案7】:

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

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

【讨论】:

    【解决方案8】:

    当然,如果他在路径上运行不同的程序,则使用 start-process 的建议是可以的。但是,如果您想在特定目录(例如您的项目目录)中运行一些 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))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-19
      • 2021-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多