4

我想要一些 Emacs lisp 来操作来自不同 Emacs 进程的相同文件。所以我写了下面的脚本来检查它是如何lock-buffer工作的。但是,当尝试通过第二个 Emacs 进程 ( find-and-lock-file $es2 /tmp/dummy) 锁定文件时,它会停止。我需要去另一个终端并发送emacsclient --socket-name server-2 --eval '(kill-emacs)'以停止 Emacs 进程。如果我通过 来打开 UI,Emacs 会提示对文件执行什么操作emacsclient -t --socket-name server-2,但我想让这一切都在后台完成,并避免使用 Emacs 提示符来继续该过程。我怎样才能做到这一点?是否有可能使 Emacs 在无法锁定文件时引发一些错误?

编辑:@event_jr 使用file-locked-p. 我认为它在大多数情况下都有效。file-locked-p但是,我认为其他 Emacs 进程可以在和执行之间锁定文件lock-buffer所以,我会保持这个问题的开放性。解决了。谢谢,@event_jr!

#!/bin/bash
es1="server-1"
es2="server-2"

start-server () {
    emacs -q --daemon --eval "(progn (setq server-name \"$1\") (server-start) (require 'cl))"
}

emacs-eval () {
    echo "@$1 >>> $2"
    emacsclient --socket-name "$1" --eval "$2"
}

kill-emacs () {
    emacs-eval "$1" '(kill-emacs)'
}

find-and-lock-file () {
    emacs-eval "$1" "(progn (find-file \"$2\") (set-buffer-modified-p t) (lock-buffer))"
}

start-server $es1
start-server $es2

find-and-lock-file $es1 /tmp/dummy
find-and-lock-file $es2 /tmp/dummy

kill-emacs $es1
kill-emacs $es2
4

2 回答 2

4

似乎没有办法emacsclient --eval返回错误代码。但是你可以让它打印你需要知道的东西:

#!/usr/bin/env bash

es1="server-1"
es2="server-2"

emacs=/Applications/Emacs.app/Contents/MacOS/Emacs
[ -e $emacs ] || emacs=emacs

start-server () {
  read -r -d '' script <<EOF
(progn
  (setq server-name "$1")
  (server-start)
  (require 'cl)

  (defun my-set-buffer-modified-p (flag)
    (flet ((ask-user-about-lock
              (&rest args)
;;              (signal 'file-locked args)
              (apply 'error "%s was locked by %s" args)))
      (set-buffer-modified-p flag))))
EOF

  $emacs -q --daemon --eval "$script"
}

emacs-eval () {
    echo "@$1 >>> $2"
  emacsclient --socket-name "$1" --eval "$2"
}

kill-emacs () {
  emacs-eval "$1" '(kill-emacs)'
}

find-and-lock-file () {
  read -r -d '' script <<EOF
(with-current-buffer (find-file-noselect "$2")
  (my-set-buffer-modified-p t))
EOF

  emacs-eval "$1" "$script"

}

start-server $es1
start-server $es2

find-and-lock-file $es1 /tmp/dummy
find-and-lock-file $es2 /tmp/dummy

kill-emacs $es1
kill-emacs $es2

编辑:我对源代码进行了一些挖掘,并找到了对 的引用 ask-user-about-lock,这很好地解决了它。

于 2012-03-08T15:57:24.357 回答
0

我找到了另一个答案,使用run-with-timer, 绕过 emacsclient --eval 错误,以便我可以检查它(signal 'file-locked ...)在“正常”情况下是否有效。

#!/usr/bin/env bash

es1="server-1"
es2="server-2"

emacs=/Applications/Emacs.app/Contents/MacOS/Emacs
[ -e $emacs ] || emacs=emacs

start-server () {
  read -r -d '' script <<EOF
(progn
  (setq server-name "$1")
  (server-start)
  (require 'cl)
  (defvar my-file-is-locked "undefined")

  (defun my-set-buffer-modified-p (flag)
    (flet ((ask-user-about-lock
              (&rest args)
              (setq my-file-is-locked "no")
              (signal 'file-locked args)))
      (set-buffer-modified-p flag)
      (setq my-file-is-locked "yes"))))
EOF

  $emacs -q --daemon --eval "$script"
}

emacs-eval () {
    echo "@$1 >>> $2"
  emacsclient --socket-name "$1" --eval "$2"
}

kill-emacs () {
  emacs-eval "$1" '(kill-emacs)'
}

find-and-lock-file () {
  read -r -d '' script <<EOF
(run-with-timer 0 nil (lambda ()
  (with-current-buffer (find-file-noselect "$2")
    (my-set-buffer-modified-p t))))
EOF

  emacs-eval "$1" "$script"
}

file-locked-p () {
  emacs-eval "$1" "(message \"my-file-is-locked = %s\" my-file-is-locked)"
}

start-server $es1
start-server $es2

find-and-lock-file $es1 /tmp/dummy
find-and-lock-file $es2 /tmp/dummy

file-locked-p $es1
file-locked-p $es2

kill-emacs $es1
kill-emacs $es2
于 2012-03-12T16:31:37.913 回答