求教:(current-buffer) 的变动是发生在哪里?

我在 ~/tmp/a.txt 这个buffer上,执行命令: magit-log-buffer-file
明明这个函数前后都显示 (current-buffer) 是a.txt
但为什么,最终的buffer是 magit-log(master -- a.txt): tmp ?
这个 (current-buffer) 的变动发生在什么地方?

类似的还有 about-emacs 命令,我都找出来变动是怎么发生的。

自己查看源代码,使用 display-buffer、switch-to-buffer 之类的函数。

当然是读过代码了,
从代码里看不出什么时候切buffer
否则也不会来问

你又没说你已经看过代码但没看明白,我怎么知道你有没看过?

以 about-emacs 为例:

display-about-screen -> fancy-about-screen -> (switch-to-buffer “About GNU Emacs”)

@xuchunyang

但是,他明明把switch-to-buffer 包在 save-selected-window里面了嘛。

事实上,在函数体前后各看一下current-buffer,并没有变化啊。

这个才是我迷惑的地方

@goumao 意思是这个吧

(progn
  (message "first %s" (buffer-name))
  (view-external-packages)
  (message "second %s" (buffer-name))
  )
;; => 
;; first *scratch*
;; second *info*
;; "second *info*"


(progn
  (message "first %s" (buffer-name))
  (about-emacs)
  (message "second %s" (buffer-name))
  )
;; =>
;; first *scratch*
;; second *scratch*    ??? 这里为什么不是显示 *About GNU Emacs* 
;; "second *scratch*"

从代码里来讲,second那里,就是应该是 scratch

那么问题来了,这个命令都结束了,current-buffer还是 scratch
那么,什么东西触发它变成了 About GNU Emacs

我写sis,多个issue都跟这块的机制有关。

(progn
  (message "first %s" (buffer-name))
  (about-emacs)
  (setq test-timer (run-with-timer 0 nil 
				   (lambda()
				     (message "second %s" (buffer-name))
				     )))
  )
  ;; (cancel-timer test-timer)

;; =>
;; first *scratch*
;; [nil 24360 8833 460506 nil (lambda nil (message "second %s" (buffer-name))) nil nil 0]
;; second *About GNU Emacs*      加个延时正常了???

对啊。。。

关键是,为什么延时之后,current-buffer 就变了。。

相关的代码在什么地方?

第一个例子里 (view-external-packages) second 那里可是直接变成了 *info*

我是不明白,不过这个0s延时既然可以判断current-buffer发生变化,不用管这个不行吗?

@emacle
我指的是about-emacs
因为这块的代码我分析过,
按道理来讲,current-buffer是不应该改的。

@emacle workaround归wordaround,不是正途嘛

哈哈,太难了太难了,坐等大佬们来解惑

大佬,求看看我们刚才的分析
点拨两句

这是command loop做的特殊处理

https://www.gnu.org/software/emacs/manual/html_node/elisp/Current-Buffer.html

When an editing command returns to the editor command loop, Emacs automatically calls set-buffer on the buffer shown in the selected window. This is to prevent confusion: it ensures that the buffer that the cursor is in, when Emacs reads a command, is the buffer to which that command applies (see Command Loop). Thus, you should not use set-buffer to switch visibly to a different buffer; for that, use the functions described in Switching Buffers.

好像是我要的答案。。。

我在仔细研究一下~~~

另外,@YangZhao11 你的头像,发型很酷 :joy:

我也碰到这个问题,我在 imbot 里把 post-command-hook 和 buffer-list-update-hook 结合起来,貌似可以解决这个问题。

@emacle

现在原因知道了,
我觉得,你这个方案完美。

@QiangF

哇,你也注意到这个问题了哇
我第一次碰到 about-emacs
看了几天代码也没看出头绪
第二次碰到magit-log-buffer-file
知道是共性问题了。
后面只有更多。。。

能详细解释一下不,那个全英文实在不懂,学习一下