Use completing-read
command. The function will look like
(defun app ()
(interactive)
(let ((app-name (completing-read "Run application: " program-list)))
(async-shell-command app-name)))
Possibly more idiomatic is to use interactive
instead of assigning to a variable according to Emacs Lisp Idioms: Prompting for User Input:
(defun app (app-name)
(interactive (list (completing-read "Run application: " app-list)))
(async-shell-command app-name))
Also you can use (start-process app-name nil app-name)
instead of (async-shell-command app-name)
, if you don't care for process output according to Run a program from Emacs and don't wait for output.
See Minibuffer Completion for more ideas on completion in Emacs and Asynchronous Processes for calling processes from Emacs, both from GNU manuals.