Как заставить буфер блокировки Emacs выйти из строя, если он не может заблокировать файл?

StackOverflow https://stackoverflow.com//questions/9608715

  •  09-12-2019
  •  | 
  •  

Вопрос

Я хочу, чтобы какой-нибудь Emacs Lisp мог манипулировать одним и тем же файлом из разных процессов Emacs.Поэтому я написал следующий скрипт, чтобы проверить, как lock-buffer работает.Однако он останавливается при попытке заблокировать файл вторым процессом Emacs (find-and-lock-file $es2 /tmp/dummy).Мне нужно перейти к другому терминалу и отправить emacsclient --socket-name server-2 --eval '(kill-emacs)' чтобы остановить процесс Emacs.Emacs подскажет, что делать с файлом, если я открою пользовательский интерфейс, выполнив emacsclient -t --socket-name server-2, но я хочу, чтобы все это выполнялось в фоновом режиме и не использовалось приглашение Emacs для продолжения процесса.Как я могу это сделать?Можно ли заставить Emacs выдавать ошибку, когда ему не удается заблокировать файл?

РЕДАКТИРОВАТЬ:@event_jr предложил ответ, используя file-locked-p.Я думаю, что это работает большую часть времени.Однако я думаю, что другой процесс Emacs может заблокировать файл между выполнением file-locked-p и 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
Это было полезно?

Решение

Кажется, нет способа сделать 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, который прекрасно решает эту проблему.

Другие советы

Я нашел другой ответ, используя 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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top