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?

4
  • 3
    You're probably looking for `shell-command-to-string'.
    – politza
    Commented Jun 28, 2015 at 20:53
  • Related question.
    – Malabarba
    Commented Jun 28, 2015 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
    Commented Jun 28, 2015 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!!! Commented Jul 1, 2015 at 19:20

2 Answers 2

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)
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.

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.