How to make Emacs lock buffer fail if it cannot lock a file?

I want Emacs lisp to work with the same file from different Emacs processes. So I wrote the following script to check how lock-buffer works. However, it stops when trying to lock the file with the second Emacs process ( find-and-lock-file $es2 /tmp/dummy ). I need to go to another terminal and send emacsclient --socket-name server-2 --eval '(kill-emacs)' to stop the Emacs process. Emacs asks what to do for the file if I open the user interface emacsclient -t --socket-name server-2 , but I want to do all this in the background and not use the Emacs prompt to continue the process. How can i do this? Is it possible to make Emacs some kind of error if the file cannot be locked?

EDIT : @event_jr suggested an answer using file-locked-p . I think this works most of the time. However, I think another Emacs process may lock the file between executing file-locked-p and lock-buffer . So, I will leave this question open. It is resolved. Thank @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
source share
2 answers

There seems to be no way to make emacsclient --eval return emacsclient --eval . But you can print out what you need to know:

 #!/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 

EDIT: I tricked the source a bit and found a link to ask-user-about-lock that solves it perfectly.

+4
source

I found another answer using run-with-timer to get around the emacsclient --eval error, so that I can verify that (signal 'file-locked ...) works in a β€œnormal” situation.

 #!/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 
0
source

Source: https://habr.com/ru/post/1400277/


All Articles