65 votes

Filtrer du texte par une commande shell dans Emacs

En vi[m] il y a le ! qui me permet d'acheminer du texte à travers une commande shell -- comme trier ou indenter -- et récupérer le texte filtré dans le tampon. Y a-t-il un équivalent dans emacs ?

Merci,

Rohit

112voto

link0ff Points 1565

Vous pouvez sélectionner une région et taper `C-u M-| commande RET', et il remplace la région avec la sortie de la commande dans le même tampon grâce à l'argument préfixe interactif de shell-command-on-region.

17voto

Greg Mattes Points 9578

J'ai écrit ceci il y a quelques années, ça pourrait vous aider :

(defun generalized-shell-command (command arg)
  "Unifies `shell-command' and `shell-command-on-region'. If no region is
selected, run a shell command just like M-x shell-command (M-!).  If
no region is selected and an argument is a passed, run a shell command
and place its output after the mark as in C-u M-x `shell-command' (C-u
M-!).  If a region is selected pass the text of that region to the
shell and replace the text in that region with the output of the shell
command as in C-u M-x `shell-command-on-region' (C-u M-|). If a region
is selected AND an argument is passed (via C-u) send output to another
buffer instead of replacing the text in region."
  (interactive (list (read-from-minibuffer "Shell command: " nil nil nil 'shell-command-history)
                     current-prefix-arg))
  (let ((p (if mark-active (region-beginning) 0))
        (m (if mark-active (region-end) 0)))
    (if (= p m)
        ;; No active region
        (if (eq arg nil)
            (shell-command command)
          (shell-command command t))
      ;; Active region
      (if (eq arg nil)
          (shell-command-on-region p m command t t)
        (shell-command-on-region p m command)))))

J'ai trouvé cette fonction très utile. Si vous la trouvez également utile, je vous suggère de la lier à une touche de fonction pour plus de commodité, personnellement j'utilise F3 :

(global-set-key [f3] 'generalized-shell-command)

9voto

dmckee Points 50318

Montage tardif : Même si j'apprécie les upvotes, la réponse de Jurta est la meilleure. Et le hack de Greg est plus soigné que le mien.

Je vais laisser le reste ici parce que ça peut valoir quelque chose, mais...


M-x shell-command-on-region qui semble être lié à M-| par défaut.


Je vois que cela ne fait pas exactement ce que Rohit a demandé. En utilisant C-h f shell-command-on-region révèle que le comportement souhaité est disponible dans la version non interactive de la commande (en définissant l'argument replace à non nul). Nous devrions être en mesure d'écrire un wrapper pour faire cela.

Essayez ceci (chargez-le dans *scratch* et exécuter M-x eval-buffer si cela fonctionne, copiez-le dans votre fichier .emacs) :

(defun shell-command-on-region-replace (start end command)
  "Run shell-command-on-region interactivly replacing the region in place"
  (interactive (let (string) 
         (unless (mark)
           (error "The mark is not set now, so there is no region"))
         ;; Do this before calling region-beginning
         ;; and region-end, in case subprocess output
         ;; relocates them while we are in the minibuffer.
         ;; call-interactively recognizes region-beginning and
         ;; region-end specially, leaving them in the history.
         (setq string (read-from-minibuffer "Shell command on region: "
                            nil nil nil
                            'shell-command-history))
         (list (region-beginning) (region-end)
               string)))
  (shell-command-on-region start end command t t)
  )

Et notez comme je le dis dans les commentaires que ce n'est pas une chose très emacsy à faire. Mais je pense que cela fonctionne.


Pour les lecteurs qui ne savent pas comment sélectionner une région :

  1. Déplacez le "point" (position actuelle du curseur) à une extrémité de la région, et utilisez la fonction C-space pour activer la " marque ".
  2. Déplacer le point à l'autre extrémité de la région
  3. Vous avez terminé, invoquez la commande

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X