2

Suppose we have a collection of descriptions like this:

("procedural" "functional" "high-level" "low-level" "statically-scoped" "dynamically-scoped")

Suppose that we have a database of programming languages and would like to enable the user to enter queries like this:

(or (and procedural high-level) dynamically-scoped)

with completion aid for the words from the collection. I have looked at (ido-)completing-read, but it seems to match the whole input string instead of individual words. With what tool can I achieve the desired behavior?

AlwaysLearning
  • 749
  • 4
  • 14
  • Have you tried letting the user work in a temporary buffer to construct the query expression, completing individual names in that buffer using `completion-at-point`? – Drew Aug 01 '17 at 20:19
  • @Drew Why do you say "a temporary buffer"? Can't completion work in the mini-buffer? Please see my post where I report trying this out: https://emacs.stackexchange.com/q/34593/16048 – AlwaysLearning Aug 01 '17 at 21:52
  • Yes, it can. I just thought it might be less confusing for a user and easier for you, since you don't have to bother with the minibuffer keymaps. – Drew Aug 01 '17 at 23:42
  • @Drew I tried to pass the company mode's keymap to `read-from-buffer` in the post that I cited in my comment above and it still did not work... – AlwaysLearning Aug 02 '17 at 06:13
  • You may want to look at the source of `regexp-builder` as the way you describe the interaction is similar to what it does. You may also find http://sphinxsearch.com/ to be of interest since it has a query language similar to what you describe and can produce results later useful for completion (it can sort the search results intelligently based on query parameters). – wvxvw Aug 02 '17 at 06:43
  • @wvxvw I don't see the similarity between `regexp-builder` and what I am describing... – AlwaysLearning Aug 02 '17 at 09:08
  • Sorry, I got confused by the comments suggesting "a temporary buffer". – wvxvw Aug 02 '17 at 09:12
  • Also, you may find that Prolog already offers a very similar interface. Unless you know this already, a Prolog program consists of a database (the part written by the programmer, typically the larger body of the whole product), and the interactive prompt, where users can query the database (created dynamically, while using the database). There are also some bindings of Prolog to relational databases, s.a. SQLite. I'd be very interested to see an integration of Prolog with Emacs, where you could query a database in a "prolog way" from minubuffer. – wvxvw Aug 02 '17 at 09:17

1 Answers1

1

Here is a complete solution based on this discussion:

(require 'company)
(require 'cl-lib)

(defconst sample-completions
  '("procedural" "functional" "high-level" "low-level" "statically-scoped" "dynamically-scoped"))

;; This function is based on http://sixty-north.com/blog/writing-the-simplest-emacs-company-mode-backend
(defun company-sample-backend (command &optional arg &rest ignored)
  (interactive (list 'interactive))
  (let ((my-completions (copy-sequence sample-completions)))
    (cl-case command
      (interactive (company-begin-backend 'company-sample-backend))
      (prefix (and t ;(eq major-mode 'fundamental-mode)
           (company-grab-symbol)))
      (candidates
       (cl-remove-if-not
    (lambda (c) (string-prefix-p arg c))
    my-completions)))))

(define-key company-mode-map (kbd "TAB") 'company-sample-backend)

(setq resize-mini-windows t)

(defun my-minibuffer-mode ()
  (company-mode 1))

We can now perform the input without altering the normal function of the mini-buffer as follows:

(let ((company-backends (copy-sequence company-backends))
      (minibuffer-setup-hook (copy-sequence minibuffer-setup-hook)))
  (add-to-list 'company-backends 'company-sample-backend)
  (add-hook 'minibuffer-setup-hook 'my-minibuffer-mode)
  (read-from-minibuffer "Prompt: "))

Acknowledgement: thank you very much to everyone for their comments.

AlwaysLearning
  • 749
  • 4
  • 14