index all rss twitter github linkedin email

Álvaro Ramírez

13 January 2019 Swapping Emacs ivy collections/sources

Ivy is great. I've been meaning to figure out a way to swap sources while running ivy. This would enable me to cycle through different sources using the existing search parameters.

At first look, 'ivy-set-sources seemed like the right choice, but it's used during setup to agregate sources. Subsequent 'ivy-set-sources calls are ignored during an 'ivy-read session.

There's an ivy feature request over at github with a similar goal in mind. Although the feature is not yet supported, there's a handy suggestion to use 'ivy-quit-and-run to quit the current command and run a different one.

With 'ivy-quit-and-run in mind, we can write our 'ar/ivy-read function to take a list of sources and add a little logic to cycle through them using a keybiding, in my case <left> and <right>.

;;; -*- lexical-binding: t; -*-

(require 'cl)

(cl-defstruct
    ar/ivy-source
  prompt
  collection
  action)

(cl-defun ar/ivy-read (sources &key index initial-input)
  (let ((kmap (make-sparse-keymap))
        (source))
    (cl-assert (> (length sources) 0))
    (when (null index) (setq index 0))
    (setq source (nth index sources))
    (define-key kmap (kbd "<right>") (lambda ()
                                       (interactive)
                                       (ivy-quit-and-run (ar/ivy-read sources
                                                                      :index (if (>= (1+ index)
                                                                                     (length sources))
                                                                                 0
                                                                               (1+ index))
                                                                      :initial-input ivy-text))))
    (define-key kmap (kbd "<left>") (lambda ()
                                      (interactive)
                                      (ivy-quit-and-run (ar/ivy-read sources
                                                                     :index (if (< (1- index)
                                                                                   0)
                                                                                (1- (length sources))
                                                                              (1- index))
                                                                     :initial-input ivy-text))))
    (ivy-read (ar/ivy-source-prompt source)
              (ar/ivy-source-collection source)
              :action (ar/ivy-source-action source)
              :initial-input initial-input
              :keymap kmap)))

(defun ar/ivy-food-menu ()
  (interactive)
  (ar/ivy-read (list
                (make-ar/ivy-source :prompt "Pizza: "
                                    :action (lambda (selection)
                                              (message "Selected pizza: %s" selection))
                                    :collection (lambda (str pred v)
                                                  (list "Bianca Neve - Mozzarella, Ricotta, Sausage, Extra Virgin Olive Oil, Basil"
                                                        "Boscaiola - Mozzarella, Tomato Sauce, Sausage, Mushrooms, Extra Virgin Olive Oil, Basil"
                                                        "Calzone - Ricotta, Ham, Mushrooms, Artichokes. Topped with Tomato Sauce and Extra Virgin Olive Oil."
                                                        "Capricciosa - Mozzarella,Tomato Sauce, Prosciutto Cotto Ham, Mushrooms, Artichokes, Extra Virgin Olive Oil."
                                                        "Carciofi - Mozzarella, Tomato Sauce, Artichokes, Extra Virgin Olive Oil, Basil."
                                                        "Diavola - Mozzarella, Tomato Sauce, Spicy Salami, Extra Virgin Olive Oil, Basil."
                                                        "Funghi - Mozzarella, Tomato Sauce, Mushrooms, Extra Virgin Olive Oil, Basil.")))
                (make-ar/ivy-source :prompt "Tacos: "
                                    :action (lambda (selection)
                                              (message "Selected taco: %s" selection))
                                    :collection (lambda (str pred v)
                                                  (list "Pork pibil - Slow cooked in citrus & spices, with pink pickled onions."
                                                        "Grilled chicken & avocado - Ancho rub, guacamole & green tomatillo salsa."
                                                        "Plantain - Sweet & spicy chipotle & crumbled feta."
                                                        "Poblano pepper - Caramelised onions, corn & cashew nut mole."
                                                        "Buttermilk chicken - Served crispy fried with habanero & white onion relish & spiced mayo."
                                                        "Sustainable battered cod - mSC certified cod with shredded slaw, chipotle mayo & pickled cucumber."
                                                        "Chargrilled steak - Avocado & chipotle salsas.")))
                (make-ar/ivy-source :prompt "Burgers: "
                                    :action (lambda (selection)
                                              (message "Selected burger: %s" selection))
                                    :collection (lambda (str pred v)
                                                  (list "The cheese - Aged beef patty with american cheese, gherkins, ketchup & mustard."
                                                        "The yeah! - Aged beef patty with american cheese, gherkins, yeah! sauce & salad."
                                                        "The yfc or hot yfc - Crispy chicken with lime or chipotle crema, lettuce, pickled onion & slaw."
                                                        "The rancher - Grilled chicken with ranch dressing, bacon & salad."
                                                        "The bubbah - Aged beef patty with smokey aubergine, pickled red cabbage, lettuce, roast toms, onions & cheddar."
                                                        "The bulgogi - Sesame-spiced beef patty with miso mayo, pickled radish, onion, cucumber & spring onion."
                                                        "The summer - Aged beef patty with sriracha mayo, lettuce, onion, toms, avo, cheddar & bacon."))))))

ivy-cycle-sources.gif

ps. Menu data from Star of Kings, Wahaca, and Pizzarino.