I would like to make a table that shows what minibuffer completion frameworks have been loaded from icomplete, icomplete-vertical, ivy, vertico and helm. As well as the minibuffer completion framework currently in place.

Have started with the following

(defun make-table ()
  (table-insert 4 5)
  (table-insert-sequence "icomplt-horz" 1 4 1 'center)
  (table-forward-cell 4)
  (table-insert-sequence "icomplt-vert" 1 4 1 'center)

Have not figured out how to move by row yet. Most of the examples I have seen were about org-tables.

  • 1
    What have you tried? Please edit the question and add your attempts.
    – NickD
    Commented Nov 4, 2022 at 14:25
  • You can create an Org table in an Org mode file and then use org-table-convert to convert it to a table.el table.
    – NickD
    Commented Nov 4, 2022 at 16:02
  • I would like to insert the table in a dedicated buffer actually, which would not necessarily be in org-mode.
    – Dilna
    Commented Nov 4, 2022 at 16:10
  • 1
    Try reading the Commentary in the table.el file: it may have some information about programmatic interfaces. That's the second place I look for information about a package. This one has an extensive Commentary.
    – NickD
    Commented Nov 4, 2022 at 18:29
  • 1
    Have you considered using table-capture? Seems the easiest path to me... Commented Nov 4, 2022 at 20:24

1 Answer 1


IMO, the most important thing here is to get the data: formatting the data as a textual table is of secondary importance, but you seem stuck on that, so here's one way to proceed.

You write a function that produces the data as text with column fields delimited by some character and rows delimited by (e.g.) newlines. Then you use M-x table-capture to convert the region to a table.

For example if you have text like this:


then marking the region appropriately, doing M-x table-capture, and answering the questions ("Column delimiter regexp: @", "Row delimiter regexp: C-q C-j", "Justify (default left): RET", "Minimum cell width (default 5): RET") will create the table:

|built-in  |yes     |
|helm      |no      |
|ivy       |no      |
|icomplete |no      |
|vertico   |no      |

(I get white letters on a blue background in each cell - YMMV).

You can do that programatically, assuming you know the bounds of the region, with:

(table-capture beg end "@" "\n")

where beg and end are the beginning and the end of the region that you are interested in. For experimentation, you can type that expression in your text buffer and execute it with C-x C-e after the closing paren. If you don't like the result, undo with C-x u and re-execute the command after whatever changes you deem necessary.

The main problem is to produce the text that will become the table, but now you don't have to worry about the table at all. You can produce the table in a form that's convenient for manipulation, then convert that representation into text that can be inserted in the buffer and then insert that text and call table-capture as described above to convert it into a table.

Here is an implementation of that idea:

  (defun make-table ()
    (let ((beg (point)))
      (insert (text-of-table (table-of-frameworks)))
      (table-capture beg (point) "@" "\n")))

where I postulate the existence of two additional functions: table-of-frameworks and text-of-table.

The function table-of-frameworks produces a list of completion frameworks and whether they are loaded in the current emacs in the form of two-element lists like this:

(("ivy" "yes") ("helm" "no") ...)

It does not worry about the built-in completion since that's always available:

  (defun table-of-frameworks ()
    "The returned table is represented as a list of rows; each row is
  represented as a two-element list: the name of the framework and
  the string \"yes\" or \"no\", depending on whether the framework is present or not."
    (let ((frameworks '(ivy helm vertico icomplete)))
      (mapcar (lambda (x) (list (symbol-name x) (if (featurep x) "yes" "no"))) frameworks)))

The text-of-table function function converts this representation of the table into a single string that can be inserted as the make-table function does:

  (defun text-of-table (table)
    "Insert a header and the first row  and then loop over the table,
  formatting each row and concatenating the rows with newlines."
    (concat "Framework@Present?\n" "built-in@yes\n"
            (mapconcat (lambda (x) (format "%s@%s\n" (nth 0 x) (nth 1 x))) table "\n")))

  • 1
    table.el looks as if it was designed under the assumption that the table would be edited interactively rather than from elisp. It could have a lot of potential, if some could contribute to the code and doc if it proves necessary.
    – Dilna
    Commented Nov 5, 2022 at 7:22
  • I do not want to have the row separators, between built-in and vertico.
    – Dilna
    Commented Nov 5, 2022 at 11:17
  • AFAIK, you get them whether you want them or not: table.el is built this way. With Org mode tables, you can put hline separators where you want them (OTOH, if you want them everywhere that gets to be a pain).
    – NickD
    Commented Nov 5, 2022 at 12:56

Your Answer

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

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