[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

How to reliably edit a file from within Emacs Lisp and return a string?

From: Jean Louis
Subject: How to reliably edit a file from within Emacs Lisp and return a string?
Date: Thu, 22 Aug 2019 23:31:03 +0200
User-agent: Mutt/1.10.1 (2018-07-13)

I need to reliably edit the file from within Emacs Lisp, and then
return the string by reading the file. And I have difficulties in
doing so.

Purpose of it is to read database field values, and feed them back
into the database. I have been doing that for years, reliably, because
I was calling Emacs from outside of Emacs. For example, common lisp
would wait for the Emacs to finish editing and then it would read the
file as a string.

Since I have switched to editing within Emacs, I am forced so far to
use various tricks like (recursive-edit) and similar. I am forced to
quit editing with C-c C-c or C-M-c which is all not reliable, as if
mode chances, maybe C-c C-c changes, killing the buffer is also not
conclusive for Emacs Lisp, basically from within Emacs Lisp, how can I
know that find-file has finished its job, that buffer has been closed,
so that I can read the string?

Function like this one below is just an alternative, but it is simply
not reliable, as too many things can happen with the buffer, and I
better rely on temporary files, and not temporary buffers for database
field value editing.

(defun read-from-buffer (value &optional buffer-name)
  "Edits string and returns it"
  (let ((this-buffer (buffer-name))
        (new-value value)
        (buffy (if buffer-name buffer-name "*edit-string*")))
      (switch-to-buffer buffy)
      (set-buffer buffy)
      (setq header-line-format "➜ Finish editing with C-c C-c or C-M-c")
      (local-set-key (kbd "C-c C-c") 'exit-recursive-edit)
      (if (stringp value) (insert value))
      (speak "You may quit the buffer with Control C Control C")
      (message "When you're done editing press C-c C-c or C-M-c to continue.")
        (if (get-buffer-window buffy)
              (setq new-value (buffer-substring (point-min) (point-max)))
              (kill-buffer buffy))))
      (switch-to-buffer this-buffer)

The function like this one below is simply not perfect. The `a` will
be set on the end only if I press C-M-c, while C-c C-c will mostly
be changed as keybinding if I change the mode, like changing to Org
mode, the C-c C-c is also changing.

(defun edit-temp-file (file)
  "Edits temporary file and returns it as string"
  (let ((created (create-file-buffer file))
        (buffer (get-file-buffer file)))
    (switch-to-buffer created)
    (set-visited-file-name file)
    (if (file-exists-p file)
        (insert (file-to-string file)))
    (message "Hit C-M-c when done") 
    ;; (add-hook 'kill-buffer-hook 'exit-recursive-edit 0 t) ;; just thinking
    ;; (local-set-key (kbd "C-x k") 'exit-recursive-edit)    ;; just thinking
    ;; (set-register 77 (recursive-edit))                    ;; just thinking 
    ;; (speak "Finished editing")) ;; This way I can know what happened
  (kill-buffer buffer)
  (file-to-string file)))

(defun file-to-string (file)
  "File to string function"
    (insert-file-contents file)

(setq a (edit-temp-file ""))

What I really need is following:

- to be able to provide file name to Emacs Lisp function

- for Emacs Lisp to have it know with guarantee that buffer has been
  killed, if saved or not saved, is left to editing choice,

- for Emacs Lisp to read the string after buffer has been killed

To repeat again, to do that is extremely easy from outside programming
language. I supply the file, edit it with emacs, and once finished, I
read the file into string.

My concept is of course following:

(defun edit-temp-file (file)
  (find-file file)
  (file-to-string file))

But of course I am not getting the result. If anybody knows the solution, let 
me know.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]