How to write a decent process filter?
- by konr
Hi there,
I'm building a program that communicates with Emacs, and one of the challenges I'm facing is writing Emacs's process filter function. Its input string is a series of s-expressions to be evaluated. Here is a sample:
(gimme-append-to-buffer "25 - William Christie dir, Les Arts Florissants - Scene 2. Prelude - Les Arts Florissants\n")
(gimme-append-to-buffer "26 - William Christie dir, Les Arts Florissants - Cybele: 'Je Veux Joindre' - Les Arts Florissants\n")
(gimme-append-to-buffer "27 - William Christie dir, Les Arts Florissants - Scene 3. Cybele: 'Tu T'Etonnes, Melisse' - Les Arts Florissants\n")
(gimme-append-to-buffer "28 - William Christie dir, Les Arts Florissants - Cybele: 'Que Les Plus Doux Zephyrs'. Scene 4. - Les Arts Florissants\n")
(gimme-append-to-buffer "29 - William Christie dir, Les Arts Florissants - Entree Des Nations - Les Arts Florissants\n")
(gimme-append-to-buffer "30 - William Christie dir, Les Arts Florissants - Entree Des Zephyrs - Les Arts Florissants\n")
(gimme-append-to-buffer "31 - William Christie dir, Les Arts Florissants - Choeur Des Nations' 'Que Devant Vous' - Les Arts Florissants\n")
(gimme-append-to-buffer "32 - William Christie dir, Les Arts Florissants - Atys: 'Indigne Que Je Suis' - Les Arts Florissants\n")
(gimme-append-to-buffer "33 - William Christie dir, Les Arts Florissants - Reprise Du Choeur Des Nations : 'Que Devant Nous' - Les Arts Florissants\n")
(gimme-append-to-buffer "34 - William Christie dir, Les Arts Flor*emphasized text*issants - Reprise De L'Air Des Zephyrs - Les Arts Florissants\n")
The first problem that I've faced is that the string is somehow not fully formed when the function is so called, so writing something like (mapcar 'eval (format "(%s)" input-string)) won't work.
To deal with this first problem, I was using a loop. The full function I wrote is:
(defun eval-all-sexps (s)
(loop for x = (ignore-errors (read-from-string s))
then (ignore-errors (read-from-string (substring s position)))
while x
summing (or (cdr x) 0) into position
doing (eval (car x))))
Now the second problem that showed up is that the function is called twice with a somewhat large input, first with valid but partial content, then with what looks like pieces of the remaining data.
To solve this problem, I'm considering using a junk variable to hold up what remains from a loop and then concatenating it to the input of the next call, but I was wondering if you guys have any other suggestions on how to deal with such a problem more elegantly.
Thanks!