2010-05-19 4 views
3

저는 Emacs와 통신하는 프로그램을 만들고 있습니다. 제가 직면하고있는 도전 중 하나는 Emacs의 프로세스 필터 기능을 작성하는 것입니다. 입력 문자열은 평가할 일련의 s- 표현식입니다. 다음은 샘플입니다 :괜찮은 프로세스 필터를 작성하는 방법?

(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") 

내가 문자열이 그렇게 작동하지 않습니다 (mapcar 'eval (format "(%s)" input-string)) 같은 것을 쓰고, 어떻게 든 완전히 기능이 소위 때 형성되지 않는 것입니다 직면 한 첫 번째 문제.

이 첫 번째 문제를 해결하기 위해 루프를 사용하고있었습니다. 내가 쓴 전체 기능은 다음과 같습니다

(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)))) 

지금까지 보여준 두 번째 문제는 다음 나머지 조각의 모양으로 유효하지만, 부분적인 내용으로 첫째, 함수가 다소 큰 입력과 두 번 호출된다는 것이다 데이터.

이 문제를 해결하기 위해 루프에서 남아있는 것을 잡아두고 다음 호출의 입력에 연결하는 정크 변수를 사용하는 것을 고려하고 있지만 어떻게해야하는지에 대해 다른 제안이 있는지 궁금합니다. 그러한 문제를보다 우아하게 다루는 것.

감사합니다.

답변

3

내가 사용하는 쉘 모드에서 내가하는 일입니다.
출력이 완료되면 프로세스 출력에서 ​​특수 end-of-record 문자열을 찾습니다. 그때까지 나는 덩어리를 연결한다.

(defun my-shell-exec-filter (process result) 
    (let ((end-of-result (string-match my-shell-end-of-record-string result))) 
    (if (and end-of-result 
      (numberp end-of-result) 
      (> end-of-result 0)) 
     (setq my-shell-reply 
       (concat my-shell-reply 
         (substring (substring result 0 end-of-result) 0 -1))) 

     (progn 
     (setq my-shell-reply (concat my-shell-reply result)) 
     (accept-process-output process my-shell-exec-timeout 5))))) 

end-of-record 문자열이 해당 필터 fn의 여러 호출로 분할 될 수 있기 때문에 이것은 적합하지 않습니다. 따라서 올바른 것이기 위해서는 먼저 연결을 해제하고 일치 여부를 확인해야합니다. 그러나 어쨌든 당신은 아이디어를 얻습니다.

또한 매우 반복적으로 입력하면 스택 오버플로 예외가 발생할 수 있습니다. 그래서 분명히 내가 원하는만큼 깨끗하지는 않습니다.

것은이

 (setq my-shell-reply nil) 
     (set-process-filter proc my-shell-exec-filter) 
     (process-send-string proc "whatever...") 
     (if (not (accept-process-output proc my-shell-exec-timeout 100)) 
      (error "unexpected response.")) 

     ;; examine my-shell-reply here ... 
2

내 최종 솔루션으로 쫓겨되어 있었다 :

(defun eval-all-sexps (s) 
    (let ((s (concat gimme-filter-remainder s))) 
    (setq gimme-filter-remainder 
      (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)) 
       finally (return (substring s position)))))) 
관련 문제