1

I want to write a function that will write the output of wc -l <file-name> next to each file in dired mode. I got to this point:

(defun my-dired-insert-add-wc (beg end)
  (save-excursion
    (goto-char beg)
    (while (< (point) end)
      (condition-case nil
          (when (dired-move-to-filename)
            (shell-command "wc -l *")) ;; <--- `shell-command` contains what I need
        (error nil))
      (forward-line 1))))

(advice-add 'dired-insert-set-properties
            :after #'my-dired-insert-add-wc)

Now, running this outputs wc -l * into another buffer. So I decided to read shell-command to see how it works internally.

There are two things I dont understand:

  1. What role does this program play in the shell-command function? I mean, I understand that it read from the mini-buffer, but where is that fed into? Like, it's not an argument to anything else. So how does the rest of the program uses it? It's right in the beginning of the function shell-command:

    (interactive
       (list
        (read-shell-command "Async shell command: " nil nil
                (let ((filename
                       (cond
                    (buffer-file-name)
                    ((eq major-mode 'dired-mode)
                     (dired-get-filename nil t)))))
                  (and filename (file-relative-name filename))))
        current-prefix-arg
        shell-command-default-error-buffer))
    
  2. Where does the variable command gets it's value? It doesnt seems to be assigned to anywhere.

    (call-process shell-file-name nil
          (if error-file
              (list t error-file)
            t)
          nil shell-command-switch command)
    

So, to recapitaluete, I want to write the number of lines each file has in a dired buffer. I have written a small program that does something like what I want but the downside is that it outputs it into another buffer instead of the dired buffer. So I went to study the function shell-command to learn more about how to achieve my goal. I now have two question about the function shell-command.

Can someone please answer my two questions about the shell-command?

Drew
  • 75,699
  • 9
  • 109
  • 225
Jenia Ivanov
  • 427
  • 4
  • 14
  • 3
    You're probably looking for `shell-command-to-string'. – politza Jun 28 '15 at 20:53
  • [Related question](http://emacs.stackexchange.com/questions/3555/what-is-the-difference-between-a-function-and-a-command). – Malabarba Jun 28 '15 at 20:53
  • I don't see that the question has a lot to do with `interactive`. What am I missing? Should the title make clear that you are asking about **this** particular `interactive` form? Or are you in fact asking a question about the meaning of `interactive`? – Drew Jun 28 '15 at 23:18
  • I'm asking about the interactive and it's all part of a effort to write a useful function. lawlist helped me write it and tarsius explained the `interactive` works. The function `shell-command-to-string` is exactly what I needed. Thanks a lot everyone!!! – Jenia Ivanov Jul 01 '15 at 19:20

2 Answers2

5

Given the function

(defun foo (arg1 arg2)
  (interactive (list 'interactive-value1 'interactive-value2)
  (message "%s %s" arg1 arg2))

You would get

(foo 'value1 'value2) => "value1 value2"
(call-interactively 'foo) => "interactive-value1 interactive-value2"

And when actually using foo as a command

M-x foo RET => "interactive-value1 interactive-value2"

(Here => means "shows in minibuffer", usually it means "returns value").

The first result google returns when asked about "emacs interactive" is this: http://www.gnu.org/software/emacs/manual/html_node/elisp/Using-Interactive.html. You would get similar information if you did C-h f interactive RET in Emacs. Another useful key binding is C-h k, try it "on itself" (C-h k C-h k) and on C-h f too.

tarsius
  • 25,298
  • 4
  • 69
  • 109
1

Here is a working example of the project outlined by the original poster, which is based upon the comment by politza above -- the other comments and answer address the fundamental concepts at issue in the original question.

(defun my-dired-insert-add-wc ()
  (save-excursion
    (goto-char (point-min))
    (re-search-forward directory-listing-before-filename-regexp nil t)
    (while (line-move 1 t)
      (let* (
          string
          (inhibit-read-only t)
          (filename (car (dired-get-marked-files)))
          (green-light
            (and
              filename
              (not (file-directory-p filename))
              (file-exists-p filename))) )
        (when green-light
          (setq string (shell-command-to-string (concat "wc -l " filename)))
          (setq string (replace-regexp-in-string "^\s+\\|\n" "" string))
          (end-of-line)
          (insert " -- " string))))))

(add-hook 'dired-after-readin-hook 'my-dired-insert-add-wc)
lawlist
  • 18,826
  • 5
  • 37
  • 118