4

In an automated Emacs Lisp --batch/--script script I need to process the command line arguments given to the script.

I've gotten as far as getting the arguments into a list of the the form:

("--aaa=bbb" "--ccc=ddd=eee" "--blah")

Now, I need to convert them to a list of the form:

(("aaa" "bbb") ("ccc" "ddd=eee") ("blah"))

In Python I'd write something like;

   output = []
   for v in input:
     output.append(v[2:].split("=", 1))

But have been unable to convert that code to Emacs Lisp. I found Elisp split-string function to split a string by . character but wasn't able to figure out how to make it only split on the first equals.

I was heading down a route of using (substring "abcdefg" x x) with (search) from the cl package but it felt like there should be a better way? I think also want to use (mapc '<function> input) where function does the v[2:].split("=",1) part.

1
  • Note, in the original post the desired result was (("aaa" "bbb") ("ccc" "ddd") ("blah")). That is what my first solution delivers. The solution for the new demand (("test") ("aaa" "bbb") ("ccc" "ddd=eee")) is now added to my answer below. Commented Jul 14, 2014 at 10:49

1 Answer 1

3

You can use split-string. See the following code example.

(setq cmd-line '("--aaa=bbb" "--ccc=ddd=eee" "--blah"))
(setq cmd-line (mapcar (lambda (argstr)
             (when (string-match "^--" argstr)
               (split-string (substring argstr 2) "=")))
               cmd-line))

The output is (("aaa" "bbb") ("ccc" "ddd" "eee") ("blah")). That is not exactly what you want because of "eee". Maybe you can use that and just neglect "eee".

If the "eee" is really a problem a small modification helps:

(setq cmd-line '("--aaa=bbb" "--ccc=ddd=eee" "--blah"))

(setq cmd-line (mapcar (lambda (arg)
             (when (string-match "^--" arg)
               (setq arg (split-string (substring arg 2) "="))
               (if (cdr arg)
                   (setcdr (cdr arg) nil))
               arg))
               cmd-line))

The output is:

(("aaa" "bbb") ("ccc" "ddd") ("blah"))

Variant for the new requirement in the question:

(setq cmd-line '("--aaa=bbb" "--ccc=ddd=eee" "--blah"))

(setq cmd-line (mapcar (lambda (arg)
             (when (string-match "^--\\([^=]*\\)\\(?:=\\(.*\\)\\)?" arg)
               (let ((opt (match-string 1 arg))
                 (val (match-string 2 arg)))
                 (if val
                 (list opt val)
                   (list opt)))))
            cmd-line))

The output is:

(("aaa" "bbb") ("ccc" "ddd=eee") ("blah"))
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for that! I had gotten as far as your first example but ran into the "eee" problem. I don't quite understand how your second example works? Could you explain further?
Hi Tobias, I finally tested your second example and it doesn't fix the "eee" issue.
@tim-mithro-ansell That is interesting because it runs fine for me. I added the output I got in the scratch buffer. (Could you run it in the scratch buffer exactly as it is? Best regards, Tobias
@tim-mithro-ansell Now, I read the edit of your question. You added a new requirement. In the former version you demanded ("ccc" "ddd") for --ccc=ddd=eee. Now, you demand ("ccc" "ddd=eee"). I will modify my answer to meet this demand when I have some spare time.
Ahh sorry, I got my example wrong. Thanks for the fixed version, it works perfectly!

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.