2012-03-07 162 views
4

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

编辑:@event_jr使用file-locked-p提出了一个答案。我认为它大部分时间都适用。但是,我认为其他Emacs进程可以在执行file-locked-plock-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

似乎没有办法使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,解决了好听。

+0

谢谢!但是,我不相信。其他Emacs进程可能会在'(res(file-locked-p(buffer-file-name)))'和'(lock-buffer)'之间锁定文件,对吧?它会像第一个例子一样停止执行。 – tkf 2012-03-09 00:11:16

+0

你是对的。我没有涵盖所有角落案例的解决方案。这个问题越来越老,也许你应该考虑提供赏金,以便得到更多人的关注。 – 2012-03-10 06:53:16

+0

好的建议。谢谢! – tkf 2012-03-10 15:53:31

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