reddit / emacs

Making use of `completion-read-multiple`

graduale · 2022-08-30 01:20
Suppose you have a list like this: (("Apples" (:quantity 10 :location pantry)) ("Bananas" (:quantity 3 :location counter)) ("Cucumbers" (:quantity 5 :location fridge)) I want to define a function that will prompt the user with a list consisting of `Apples`, `Bananas`, and `Cucumbers`, will allow the user to choose multiple items, and will output a list consisting of all the cdr of those lists whose car was selected by the user. So, e.g. if user selects `Apples, Cucumbers`, the output will be `((:quantity 10 :location pantry) (:quantity 5 :location fridge))`. I figured out how to do a single item version of it: (setq my/list '(("Apples" (:quantity 10 :location pantry)) ("Bananas" (:quantity 3 :location counter)) ("Cucumbers" (:quantity 5 :location fridge)))) (car (cdr (assoc (completing-read "Select an item: " my/list) my/list))) (I suspect there may be better ways to do this, but it works for my purposes.) I thought `consulting-read-multiple` would allow me to do the 'multi-item' version, but apparently it does not. Or at least, I haven't figured out a way to do so. Looking at the documentation for `consulting-read-multiple` doesn't help. Here's what I see: Signature (completing-read-multiple PROMPT TABLE &optional PREDICATE REQUIRE-MATCH INITIAL-INPUT HIST DEF INHERIT-INPUT-METHOD) Documentation Read multiple strings in the minibuffer, with completion. The arguments are the same as those of completing-read. Input multiple strings by separating each one with a string that matches the regexp crm-separator. For example, if the separator regexp is ",", entering "alice,bob,eve" specifies the strings "alice", "bob", and "eve". Now, there's no `TABLE` argument to `completing-read`, whose documentation says: Signature (completing-read PROMPT COLLECTION &optional PREDICATE REQUIRE-MATCH INITIAL-INPUT HIST DEF INHERIT-INPUT-METHOD) Documentation Read a string in the minibuffer, with completion. PROMPT is a string to prompt with; normally it ends in a colon and a space. COLLECTION can be a list of strings, an alist, an obarray or a hash table. COLLECTION can also be a function to do the completion itself. PREDICATE limits completion to a subset of COLLECTION. See try-completion, all-completions, test-completion, and completion-boundaries, for more details on completion, COLLECTION, and PREDICATE. See also Info node (elisp)Basic Completion for the details about completion, and Info node (elisp)Programmed Completion for expectations from COLLECTION when it's a function. Now, *this* (setq my/list '(("Apples" (:quantity 10 :location pantry)) ("Bananas" (:quantity 3 :location counter)) ("Cucumbers" (:quantity 5 :location fridge)))) (defun my/get-value (element) (car (cdr (assoc element my/list)))) (mapcar #'my/get-value (completing-read-multiple "Select one or more items: " my/list)) seems to work. But it seems a bit baroque and I'm wondering if there is a better way to accomplish this using `completing-read-multiple` (or otherwise).
lebensterben · 2022-08-30 01:26
table should be the same as collection
graduale · 2022-08-30 01:33
That's what I thought at first, but I'm having a hard time getting things to work as I expected. If e.g. I call (car (cdr (assoc (completing-read-multiple "Select an item: " my/list) my/list))) I get `nil` as output, and not what I would have expected, which is a list each of whose element is the result of calling (car (cdr (assoc (completing-read "Select an item: " my/list) my/list))) on one of the items selecting when prompted. Am I missing something?
lebensterben · 2022-08-30 01:36
have you try to make it an alist? Currently it's not a proper alist.
graduale · 2022-08-30 12:54
Thanks. I think I was confused. I see now that what `completing-read` (and `completing-read-multiple`) return is not the element of the list whose car is selected at the prompt, but just the car of that element (and a list thereof for CRM). So I do have to do something like `mapcar` over the result of a call to `completing-read-multiple` if I want to get the values of the chosen keys.