comint 프로세스의 출력을 비동기 적으로 대기


12

우선, 면책 조항. 나는 이것을 여러 번 연구했고, 나는 이미 어떤 방법 으로든 그 답을 찾았다는 것을 확신하지만, 나는 그것을 이해하지 못한다.

내 문제는 다음과 같습니다.

  • comint를 통해 프로세스가 실행 중입니다.
  • 입력 줄을 보내고 출력을 캡처하고 끝났는지 확인하고 싶습니다 (출력의 마지막 줄이 프롬프트의 정규 표현식과 일치 할 때)
  • 프로세스가 출력 보내기를 마쳤을 때만 다른 입력 줄을 보내려고합니다 (예 :).

약간의 배경 지식은 프로그램과의 상호 작용을 구현하는 주 모드를 생각하면 임의로 임의의 양의 출력을 반환 할 수 있습니다. 이것은 특별한 상황이 아니어야합니다. 아마 입력 간에 기다려야 할 부분 은 드물지만 입력을 전체적으로 보내는 것보다 몇 가지 장점이 있습니다.

  • 출력 버퍼의 형식은 다음과 같습니다 : 입력 출력 입력 출력 ...
  • 더 중요한 것은 프로세스에 많은 텍스트를 보낼 때 텍스트가 조각으로 잘리고 조각이 프로세스에 의해 다시 붙여집니다. 절단 지점은 임의적이며 때로는 잘못된 입력을 만듭니다 (예 : 프로세스가 식별자 중간에 입력 컷을 올바르게 다시 붙여 넣지 않습니다)

어쨌든, 특이한 여부, 그것이 밝혀 되고 복잡. 지금은 라인을 따라 무언가를 사용하고 있습니다.

(defun mymode--wait-for-output ()
  (let ((buffer (mymode-get-buffer)))
    (with-current-buffer buffer
      (goto-char (point-max))
      (forward-line 0)
      (while (not (mymode-looking-at-prompt))
        (accept-process-output nil 0.001)
        (redisplay)
        (goto-char (point-max))
        (forward-line 0))
      (end-of-line))))

입력 줄을 보낸 후 다음 줄을 보내기 전에 매번 호출합니다. 글쎄 ... 그것은 작동합니다, 그것은 이미 뭔가입니다.

그러나 출력을 기다리는 동안 emacs를 정지시킵니다. 그 이유는 분명 sleep-for하며, 루프에 일종의 비동기식 (예 : 1s)을 포함하면 출력이 1s 지연되지만 교수형은 억제한다고 생각했습니다. 이런 종류의 비동기 sleep-for 는 존재하지 않는 것 같습니다 .

아니면? 더 일반적으로 emacs로 이것을 달성하는 관용적 방법이 있습니까? 다시 말해:

프로세스에 입력을 보내고 출력을 기다린 다음 비동기 적으로 더 많은 입력을 보내는 방법은 무엇입니까?

주변을 검색 할 때 (관련 질문 참조) 주로 센티넬에 대한 언급을 보았습니다 (그러나 프로세스가 완료되지 않았기 때문에이 경우에는 적용되지 않는다고 생각합니다). 후크를 로컬 버퍼로 만들고 내 "나머지 라인 평가"를 함수로 바꾸고이 함수를 후크에 추가 한 후 후크를 청소하십시오. 정말 더럽게 들리지 않습니까?).

나 자신을 명확하게하지 않거나 어딘가에 명백한 대답이있는 경우 죄송합니다. 모든 복잡한 프로세스 상호 작용으로 혼란 스럽습니다.

필요한 경우,이 예제를 모두 실용적으로 만들 수는 있지만, 이전에 찾은 모든 것과 같이 "특정 프로세스 응답이있는 특정 프로세스 질문"을 하나 더 만들 것 같습니다.

SO에 관한 몇 가지 관련 질문 :


@nicael 관련 링크에 어떤 문제가 있습니까?
T. Verron

그러나 왜 그것들을 포함시켜야합니까?
nicael

2
글쎄, 답변이 도움이되지 않더라도 관련 질문으로 나타났습니다. 누군가 나를 도와주고 싶다면 아마도 내가 가진 것보다 더 깊이있는 지식을 가지고 있을지 모르지만 아마도 미리 연구를 수행해야 할 것입니다. 이 경우 질문은 시작점을 제공합니다. 또한 언젠가 누군가가이 페이지에 방문했지만 내가 연결 한 것과 비슷한 문제가있는 경우 적절한 질문에 대한 바로 가기가 있습니다.
T. Verron

@nicael (첫 번째 게시물에서 핑을 잊어 버렸습니다. 죄송합니다.) 링크가 mx.sx가 아닌 문제입니까?
T. Verron 2009 년

확인. 수정본, 게시물로 롤백 할 수 있습니다.
nicael

답변:


19

우선, accept-process-output비동기 처리를 원한다면 사용해서는 안됩니다 . 이맥스는 사용자 입력을 기다릴 때마다 출력을 받아들입니다.

올바른 방법은 필터 기능을 사용하여 출력을 가로채는 것입니다. 보낼 회선이 있는지 여부에 따라 필터를 만들거나 삭제할 필요가 없습니다. 오히려 일반적으로 프로세스 수명 동안 단일 필터를 선언하고 버퍼 로컬 변수를 사용하여 상태를 추적하고 필요에 따라 다른 작업을 수행합니다.

저수준 인터페이스

필터 기능 은 당신이 찾고있는 것입니다. 필터 기능은 센티넬이 종료되는 것을 출력하는 것입니다.

(defun mymode--output-filter (process string)
  (let ((buffer (process-buffer process)))
    (when (buffer-live-p buffer)
      (with-current-buffer buffer
        (goto-char (point-max))
        (forward-line 0)
        (when (mymode-looking-at-prompt)
          (do-something)
          (goto-char (point-max)))))))

수동 또는 (이맥스와 함께 많은 예제 봐 grep위한 process-filter에서 .el파일).

에 필터 기능을 등록하십시오

(set-process-filter 'mymode--output-filter)

comint 인터페이스

Comint는 몇 가지 작업을 수행하는 필터 함수를 정의합니다.

  • 프로세스 출력을 포함해야하는 버퍼로 전환하십시오.
  • list에서 함수를 실행하여 comint-preoutput-filter-functions새 텍스트를 인수로 전달하십시오.
  • 에 따라 일부 임시 복제 프롬프트 제거를 수행하십시오 comint-prompt-regexp.
  • 버퍼의 끝에 프로세스 출력을 삽입하십시오
  • list에서 함수를 실행하여 comint-output-filter-functions새 텍스트를 인수로 전달하십시오.

모드가 comint를 기반으로하는 경우에 필터를 등록해야합니다 comint-output-filter-functions. comint-prompt-regexp프롬프트와 일치하도록 설정 해야합니다. Comint에는 완전한 출력 청크 (즉, 두 프롬프트 사이)를 감지하는 기능이 내장되어 있다고 생각하지 않지만 도움이 될 수 있습니다. 마커 comint-last-input-end는 마지막 입력 청크의 끝에 설정됩니다. 마지막 프롬프트가 끝나고 나면 새로운 출력 청크가 생깁니다 comint-last-input-end. 마지막 프롬프트의 끝을 찾는 방법은 Emacs 버전에 따라 다릅니다.

  • 최대 24.3까지 오버레이 comint-last-prompt-overlay가 마지막 프롬프트에 걸쳐 있습니다.
  • 24.4 이후 변수 comint-last-prompt에는 마지막 프롬프트의 시작과 끝에 대한 마커가 포함됩니다.
(defun mymode--comint-output-filter (string)
  (let ((start (marker-position comint-last-input-end))
        (end (if (boundp 'comint-last-prompt-overlay)
                 (and comint-last-prompt-overlay (overlay-start comint-last-prompt-overlay))
               (and comint-last-prompt (cdr comint-last-prompt))))
  (when (and start end (< start end))
    (let ((new-output-chunk (buffer-substring-no-properties start end)))
      ...)))

프로세스가 {수신 입력, 출력 방출, 프롬프트 표시} 이외의 순서로 출력을 방출하는 경우 보호 기능을 추가 할 수 있습니다.


comint-last-prompt-overlay 변수는 comint.el의 Emacs 25에서 정의되지 않은 것 같습니다. 다른 곳에서 왔습니까?
John Kitchin

@JohnKitchin 24.4에서 comint의 일부가 변경되었으므로 24.3에 대한 답변을 작성했습니다. 24.4 이후 방법을 추가했습니다.
Gilles 'SO- 악마 그만
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.