2

I am trying to play with the make-process function and get information from it. I am getting some errors in my process filter that I am having trouble understanding. When I run my ceedling-version function, which makes the process and associates the filter and command to the process, I get:

error in process filter: string-match: No match data, because no search succeeded
error in process filter: No match data, because no search succeeded
Version a-list: ((ceedling . 0.28.2) (cmock . 2.4.5) (unity . 2.4.2) (cexception . 1.3.1))

So it does seem to perform properly but it is still showing these errors in the process filter. I am testing with the same string that gets passed to my filter function.

I have tests that test the functions that my filter calls:

;;; Code:

(require 'ert)
(require 'ceedmacs)

(defvar test-directory "../test-data/temp_sensor")
(defvar ceedling-version-output "Welcome to Ceedling!\n  Ceedling::   0.28.2\n  CMock::      2.4.5\n  Unity::      2.4.2\n  CException:: 1.3.1\n\nProcess ceedling finished\n")

(ert-deftest version-regex-test ()
  (should (equal (regex-version "Ceedling::[[:space:]]*"   ceedling-version-output)  "0.28.2"))
  (should (equal (regex-version "CMock::[[:space:]]*"      ceedling-version-output)  "2.4.5"))
  (should (equal (regex-version "Unity::[[:space:]]*"      ceedling-version-output)  "2.4.2"))
  (should (equal (regex-version "CException::[[:space:]]*" ceedling-version-output)  "1.3.1"))
  )

(ert-deftest version-alist-test ()
  (let (version-alist)
    (setq version-alist `((ceedling   . ,(regex-version "Ceedling::[[:space:]]*"   ceedling-version-output))
                          (cmock      . ,(regex-version "CMock::[[:space:]]*"      ceedling-version-output))
                          (unity      . ,(regex-version "Unity::[[:space:]]*"      ceedling-version-output))
                          (cexception . ,(regex-version "CException::[[:space:]]*" ceedling-version-output))))
    (should (equal (alist-get 'ceedling   version-alist)  "0.28.2"))
    (should (equal (alist-get 'cmock      version-alist)  "2.4.5"))
    (should (equal (alist-get 'unity      version-alist)  "2.4.2"))
    (should (equal (alist-get 'cexception version-alist)  "1.3.1"))
    )
  )
;;; ceedmacs-test.el ends here

These tests pass just fine so I'm trying to figure out where these error in process filter messages are coming from because my process filter really doesn't do anything else besides make an alist

My code:

;;; Code:


(defvar ceedling-version-alist)


(defun regex-version (regex string)
  "Use REGEX to find version in STRING."
  (progn
    (string-match regex string)
    (string-match "[[:digit:]]*\.[[:digit:]]*\.[[:digit:]]*" string (match-end 0))
    (match-string 0 string)
    )
  )

(defun ceedmacs--version-filter (process string)
  "Filter function for PROCESS, which processes STRING to find the version.
Typical output:
     Welcome to Ceedling!
       Ceedling::   0.28.2
       CMock::      2.4.5
       Unity::      2.4.2
       CException:: 1.3.1"
  (setq ceedling-version-alist `(
                          (ceedling   . ,(regex-version "Ceedling::[[:space:]]*" string))
                          (cmock      . ,(regex-version "CMock::[[:space:]]*" string))
                          (unity      . ,(regex-version "Unity::[[:space:]]*" string))
                          (cexception . ,(regex-version "CException::[[:space:]]*" string))
                          ))
  )

(defun ceedling-version ()
  "Return association list represting ceedling version."
  (interactive)
  (let (
        (proc-name "Ceedling Process")
        version-proc
        )
      (accept-process-output
                           (make-process
                            :name proc-name
                            :command '("ceedling" "version")
                            :filter 'ceedmacs--version-filter
                            ))
      (message (format "Version a-list: %s" ceedling-version-alist))
    ))

(provide 'ceedmacs)

;;; ceedmacs.el ends here

```

On another note, I am trying to get my alist that I create in the filter process out so I am setting a global variable equal to it. Is there a better way to get information out? It seems like I could write something to a buffer and then evaluate it or do the global variable method.

Thanks for any tips, tricks, or input

2
  • 1
    Please make a minimal reproducible example. Nobody here is going to install a menagerie of C tooling and Ruby just to help you with something probably unrelated to them.
    – wasamasa
    May 4, 2018 at 20:48
  • yeah it wasn't as much a question about interfacing with ceedling as it was processing simple output from a command line tool, which is why I used the "version" argument, thinking that most cli tools have a way to output the version. I probably should have tried it with a more common cli tool. As @xuchunyang pointed out, it was an issue with the connection type I was using. I tried keeping it simple and showing with the tests that I have put thought into it and tried testing the core functionality but was running into issues with the async stuff. Sorry if the ceedling command threw you off.
    – Jesse
    May 7, 2018 at 12:15

1 Answer 1

3

You should simply use synchronous processes whenever possible, because it is simple, easy to use and reliable, for example,

(cl-loop with output = (shell-command-to-string "ceedling version")
         for line in (split-string output "\n")
         when (string-match-p "::" line)
         collect (split-string line "::" nil " +"))
;; =>
;; (("Ceedling" "0.28.2")
;;  ("CMock" "2.4.5")
;;  ("Unity" "2.4.2")
;;  ("CException" "1.3.1"))

in such case, there is no need to run ceedling version through your shell, if you mind this, you can use call-process instead of shell-command-to-string, for example,

(with-temp-buffer
  (call-process "ceedling" nil t nil "version")
  (buffer-string))

As for you question, the error message is clear enough

error in process filter: string-match: No match data, because no search succeeded
error in process filter: No match data, because no search succeeded

it means you are trying to access the match data even when the search fails. You have to check the return value of string-match to ensure the search does succeed in your regex-version.

The reason why the search is failed is Emacs doesn't receive all the output at a time, you can use M-x trace-function ceedmacs--version-filter to find it out. The reason why Emacs doesn't receive all the output at a time for such short output (~100 bytes) is you are running the process in "pty" (pseudo-terminal), this is the default by Emacs, you should usually use "pipe" instead via

(let ((process-connection-type nil))
  (make-process ...))

or

(make-process :connection-type nil ...)
3
  • So I tried ":connection-type 'pipe" because "nil" was giving me the same issue but it worked great! Thank you. I realize this is a simple example but I really wanted to do more complex things and wanted to flush out the basics of using asynchronous processes in Emacs Lisp. Thank you so much for your detailed answer, you really provided a lot of great context there. If I am going to do more asynchronous processes with more output would the pty be okay then?
    – Jesse
    May 7, 2018 at 12:08
  • @Jesse You should probably always use pipe, consult the second paragraph of (elisp) Asynchronous Processes for the difference between "pty" and "pipe".
    – xuchunyang
    May 7, 2018 at 12:57
  • I completely glossed over that paragraph, I went straight to the keyword documentation. Thanks that really clears it up!
    – Jesse
    May 7, 2018 at 13:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.