2012-03-07 164 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