首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何编写一个像样的进程过滤器?

如何编写一个像样的进程过滤器?
EN

Stack Overflow用户
提问于 2010-05-19 09:02:59
回答 2查看 513关注 0票数 3

我正在构建一个与Emacs通信的程序,我面临的挑战之一就是编写Emacs的进程过滤器函数。它的输入字符串是一系列要计算的s表达式。下面是一个示例:

代码语言:javascript
运行
复制
(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))这样的东西将不起作用。

为了处理第一个问题,我使用了一个循环。我写的完整函数是:

代码语言:javascript
运行
复制
 (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))))

现在出现的第二个问题是,函数被调用了两次,输入有点大,第一次是有效但不完整的内容,然后是看起来像是剩余数据的片段。

为了解决这个问题,我正在考虑使用垃圾变量来保存循环的剩余部分,然后将其连接到下一个调用的输入,但我想知道你们是否有任何其他建议来更优雅地处理这样的问题。

谢谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-05-19 10:58:32

这就是我使用的shell模式所做的事情。

我在流程输出中查找一个特殊的记录结束字符串,以了解输出何时完成。在此之前,我会拼接这些块。

代码语言:javascript
运行
复制
(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)))))

这是不太正确的,因为记录结束字符串可以被拆分到该过滤器fn的多次调用中。因此,为了正确,它应该首先连接,然后检查是否匹配。但不管怎样,你都明白了。

它还会递归,因此,对于非常长的输入,它可能会导致堆栈溢出异常。所以它肯定不像我想的那样干净。

这件事是以

代码语言:javascript
运行
复制
      (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 ... 
票数 3
EN

Stack Overflow用户

发布于 2010-05-31 15:47:02

我的最终解决方案是:

代码语言:javascript
运行
复制
(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))))))
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2862209

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档