GNOME + Wayland 下,使用存在的 Emacs frame 打开一个新的 buffer.

给萌新解释下,哈! 在 Emacs 里面,一个新的窗口叫做 Frame, 打开一个窗口,里面的面板叫做 Window,别搞错。如果你像我一样,在使用 Wayland + GNOME 4.5, 而且,Emacs 在 GUI 模式下使用(典型的,首先启动一个 daemon, 然后使用 emacsclient 连接到它),那么这篇文章的的技巧适合你。

这个脚本基于下面这个 GNOME extension, 以及命令行工具 jq 必须是可用的。

脚本1, wayland_activate_window, 用来激活指定 id 的 window,这里的 id 是 wayland 下的 windows id.

id=$1
gdbus call --session --dest org.gnome.Shell --object-path /org/gnome/Shell/Extensions/Windows --method org.gnome.Shell.Extensions.Windows.Activate $id

脚本2, switch_to_wayland

class_type=$1
initalize_command=${2}
command=${3-true}

ids_and_classes_in_current_workspace=$(gdbus call --session --dest org.gnome.Shell --object-path /org/gnome/Shell/Extensions/Windows --method org.gnome.Shell.Extensions.Windows.List |gdbus_json | jq -e -c '[.[] | select (.in_current_workspace == true and .frame_type == 0 and .window_type == 0) | {id: .id,wm_class: .wm_class,focus: .focus,pid: .pid}]')

read -r CURRENT_WND_ID CURRENT_WND_PID CURRENT_WND_CLASS <<< "$(echo "$ids_and_classes_in_current_workspace" |jq -j '.[] |select (.focus == true) |.id," ",.pid," ",.wm_class')"

if [[ $CURRENT_WND_CLASS != $class_type ]]; then
    id=$(echo "$ids_and_classes_in_current_workspace" |jq -e -c ".[] |select (.wm_class == \"$class_type\") |.id" |head -n1)
    if [ "$id" ]; then
        wayland_activate_window $id && $command
    else
        exec $initalize_command
    fi
fi

扔上面两个脚本到 $PATH 里,并改为可执行,用法如下:

switch_to_wayland “窗口类名称” “第一次运行执行的命令” “随后运行执行的命令(可选的)”

例如:

$: switch_to_wayland "emacs" "emacsclient -nc $@" "emacsclient -n $@"

第一次使用,会使用 emacsclient -nc 1.txt 打开一个新的 frame, 随后的使用,就会复用存在的 frame.

2 个赞