Search code examples
emacsemacs23

Passing Emacs variables to minibuffer shell commands


I can run a shell command quickly by hitting M-!. One thing I'd like to do is perform shell quick operations on the current file. An example would be checking the file out through perforce:

M-! p4 edit buffer-file-name RET

(Yes there are perforce integrations, but I'm more interested in the minishell/variable problem rather than a specific workflow)

Of course, the buffer-file-name variable is not evaluated before the command is sent to the shell.

Is there an easy on-the-fly way to do this? Or will I have to roll a custom elisp function?


Solution

  • Indeed using C-u M-: is almost right. I'm not so sure about using shell-quote-argument in eval-to-shell-argument since it only works on strings making it impossible to use eval-to-shell-argument to insert a number or a symbol. You could try something like:

    (defun sm-minibuffer-insert-val (exp)
      (interactive
       (list (let ((enable-recursive-minibuffers t))
               (read-from-minibuffer "Insert: "
                                     nil read-expression-map t
                                     'read-expression-history))))
        (let ((val (with-selected-window (minibuffer-selected-window)
                     (eval exp)))
              (standard-output (current-buffer)))
          (prin1 val)))
    

    and then bind this function in your minibuffer with (define-key minibuffer-local-map [?\M-:] 'sm-minibuffer-insert-val). Of course, if the only thing you ever want to insert is the buffer-file-name, then your execute-shell-command-on-buffer is simpler.