如何在使用 --eval 选项时让 emacsclient 等待?

如何在使用 --eval 选项时让 emacsclient 等待?

我想调用 emacs 的ediff-merge-files功能来使用 unison 文件同步器合并文件。为了避免启动新实例,我更喜欢使用emacsclient

emacsclient --eval '(ediff-merge-files "CURRENT1" "CURRENT2" nil "NEW")'

但是,emacsclient会立即返回(就像在给定纯文件和选项时一样--no-wait)。当然,unison 随后会抱怨没有编辑任何文件。

有没有办法让 emacsclient 等到我完成合并?

答案1

我发现有两种方法可以做到这一点。

将对 ediff-merge-files 的调用包装在另一个将等待调用完成的 emacs 函数中,可以尝试对启动钩子进行一些 hack,但这可能会变得非常混乱

用一个脚本包装对 emacsclient 的调用,该脚本等待新文件创建后再返回,如果临时文件是按需创建的,那么这是一个更简单的解决方案,如果新文件可能已经存在,那么你需要使用占位符文件

示例脚本 - ediff-wait,已被破解,且仅进行了最低限度的健全性检查

#!/bin/sh

[ -f $3 ] && exit 1  # merge file exists?

emacsclient --eval "( ediff-merge-files \"$1\" \"$2\" nil \"$3\" )"
while /bin/true; do
  [ -f $3 ] && exit 0
  sleep 1
done

答案2

如果您要求 Emacsclient 创建新框架,它将等待。因此,请使用以下任一方式:

emacsclient -c --eval '(ediff-merge-files "CURRENT1" "CURRENT2" nil "NEW")'如果你想创建一个图形框架或

emacsclient -t --eval '(ediff-merge-files "CURRENT1" "CURRENT2" nil "NEW")'如果你想要一个终端框架。

答案3

似乎使用 emacsclient 作为差异工具的问题在于它总是返回 0 作为状态代码,这使得 git 无法判断合并是否成功。

Mercurial wiki 上提出了一个解决方案:

#!/bin/bash

if [ $# -lt 1 ]; then
  echo 1>&2 "Usage: $0 local other base output"
  exit 1
fi

local=$1
other=$2
base=$3
output=$4

OUTPUT=`emacsclient --no-wait --eval "(ediff-merge-with-ancestor \"$local\" \"$other\" \"$base\" nil \"$output\")" 2>&1`
echo $OUTPUT | grep -v "Ediff Control Panel"

if echo "$OUTPUT" | grep -q '^*ERROR*'; then
    exit 1
fi

将其放入路径中的 shell 脚本中,一切就都好了。

[注意:此问题已在 emacs 主干中修复。]

相关内容