有办法暂时让所有Message都输出到别的地方吗?

和message相关的东西全部是写死在C里的,(比如Message buffer的名字)。

我自己写了一个蹩脚的方法,但是十分不完美。

(let ((standard-output (current-buffer)))
    (letf (((symbol-function #'message)
            #'(lambda (s &rest r) (princ (concat (apply #'format s r) "\n")))))
      (package-refresh-contents)
      nil))

执行的时候会等待整个块执行结束才显示出来,有没有办法实时显示?


后面的结果是一瞬间打印出来的。但是单单eval (package-refresh-contents) 就是一句句出来

Importing package-keyring.gpg...
Importing package-keyring.gpg...done
Contacting host: elpa.emacs-china.org:80
Contacting host: elpa.emacs-china.org:80
Package refresh done

你想解决的问题是什么?即「XY Problem」中的「X」。

话说「Y」有优雅的解决方案吗?

X:现在有一个函数,用于自动获取更新并更新所有的旧的包。

(defun package-upgrade-all ()
  "Upgrade all packages automatically without showing *Packages* buffer."
  (interactive)
  (package-refresh-contents)
  (let (upgrades)
    (cl-flet ((get-version (name where)
                           (let ((pkg (cadr (assq name where))))
                             (when pkg (package-desc-version pkg)))))
      (dolist (package (mapcar #'car package-alist))
        (let ((in-archive (get-version package package-archive-contents)))
          (when (and in-archive
                (version-list-< (get-version package package-alist) in-archive))
            (push (cadr (assq package package-archive-contents)) upgrades)))))
    (write-to-package-upgrade-history "")
    (if upgrades
        (save-window-excursion
          (dolist (package-desc upgrades)
            (let ((old-package (cadr (assq (package-desc-name package-desc) package-alist))))
              (package-install package-desc)
              (package-delete  old-package)
              (save-update-history old-package package-desc)
              (write-to-package-upgrade-history (package-desc-full-name package-desc) (package-desc-full-name old-package))))
          (write-update-history-to-cache)
          (message "{%s} Update done... [%s]" (length upgrades) (mapconcat #'package-desc-full-name upgrades ", ")))
      (write-to-package-upgrade-history "All packages are up to date"))))

(其中的 save-update-history write-to-package-upgrade-history write-update-history-to-cache 是我自定义的其他函数。)

这个函数在执行的时候会向Message中写入一堆安装的信息:

[20:14:35] Importing package-keyring.gpg...
[20:14:36] Importing package-keyring.gpg...done
[20:14:36] Contacting host: elpa.emacs-china.org:80
[20:14:40] Contacting host: elpa.emacs-china.org:80
[20:14:40] Package refresh done
[20:14:40] [18-08-23_20:14:40]
[20:14:41] Contacting host: elpa.emacs-china.org:80
[20:14:41] Generating autoloads for counsel-projectile.el...done
[20:14:42] Done (Total of 1 file compiled, 2 skipped)
[20:14:42] Package `counsel-projectile-20180822.4' deleted.
[20:14:42] [18-08-23_20:14:42]		counsel-projectile-20180822.4		->		counsel-projectile-20180822.1458
[20:14:42] Contacting host: elpa.emacs-china.org:80
[20:14:43] Contacting host: elpa.emacs-china.org:80
...

需求就是把这些信息打印在 *eshell* 里或者 *terminal* 里(当前执行命令的那个buffer),不想污染整个全局的 *Messages* buffer。

因为这些buffer可以随时杀掉,*Messages* 不想随便杀。编译产生的信息动辄几千行,完全不记录很可惜,全部记在 *Messages* 里就会导致它很卡,同时,看其他的信息也不方便。事实上在哪里操作的,就该打印在哪里,也很符合直觉。

那就不要用 (message ...)

因為 Emacs 是单任务的,在函數调用完成之前是不会 redraw display 的。

sleep-for 的 doc 也提到了

(sleep-for SECONDS &optional MILLISECONDS)

Pause, without updating display, for SECONDS seconds.

1 个赞

主要是这里面自己会时不时地调用

是有这个问题,而且也不需要 sleep-for ,这样也可以复现

(let ((standard-output (current-buffer)))
    (letf (((symbol-function #'message)
            #'(lambda (s &rest r) (princ (concat (apply #'format s r) "\n")))))
      (package-refresh-contents)
      nil))

后面的结果是一瞬间打印出来的。但是单单eval (package-refresh-contents) 就是一句句出来

Importing package-keyring.gpg...
Importing package-keyring.gpg...done
Contacting host: elpa.emacs-china.org:80
Contacting host: elpa.emacs-china.org:80
Package refresh done

我最近换上了 lsp-java ,非常好用,补全等方面完全不弱于 eclipse 。但是,它会不断地向 message 里写日志,导致我有些会开 minibuffer 的功能体验极差,比方说 ivy-yasnippet 。求解解决方案。

歪个楼,java language server用的啥?

emacs-lsp 底下的 lsp-java ? 修改 ls 启动参数就可以了:

1 个赞

Eclipse JDT Language Server

因为这里用了 async 之类的。

你的需求不是很好理解,似乎是在定制的路上走了太远。就你的问题,如果你不喜欢 message 的效果,自然就不要使用它(使用 insert),至于内置函数使用了它,就只能接受这个事实。此外,应该避免修改 message 的定义,否则 Emacs 性能变差应该不奇怪。

1 个赞

:joy: 在过度定制的道路上越走越远。。。

这人讲话贼难听的

已举报,紫薯布丁