unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: "Philip K." <philipk@posteo.net>
To: Stefan Monnier <monnier@iro.umontreal.ca>
Cc: emacs-devel@gnu.org
Subject: Re: [ELPA] New package: shell-command+
Date: Fri, 25 Sep 2020 15:52:22 +0200	[thread overview]
Message-ID: <87zh5e0xrd.fsf@posteo.net> (raw)
In-Reply-To: <jwvpn6aht5v.fsf-monnier+emacs@gnu.org> (message from Stefan Monnier on Fri, 25 Sep 2020 09:43:57 -0400)

[-- Attachment #1: Type: text/plain, Size: 310 bytes --]

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>> I wanted to submit this package I wrote a while ago. It provides an
>> interactive command named "shell-command+", that is used in the same way
>> as one uses shell-command.
>
> Sounds good.  Do you have a pointer to the code?

Oh, I forgot to attach it:


[-- Attachment #2: shell-command+.el --]
[-- Type: text/plain, Size: 5285 bytes --]

;;; shell-command+.el --- An extended shell-command -*- lexical-binding: t -*-

;; Author: Philip K. <philipk@posteo.net>
;; Version: 1.0.3
;; Keywords: unix, processes, convenience
;; Package-Requires: ((emacs "24.1"))
;; URL: http://elpa.gnu.org/packages/shell-command+.html

;; This file is NOT part of Emacs.
;;
;; This file is in the public domain, to the extent possible under law,
;; published under the CC0 1.0 Universal license.
;;
;; For a full copy of the CC0 license see
;; https://creativecommons.org/publicdomain/zero/1.0/legalcode

;;; Commentary:
;;
;; `shell-command+' is a `shell-command' substitute, that extends the
;; regular Emacs command with several features.
;;
;; A few examples of what `shell-command+' can do:
;;
;;
;; 	> wc -l
;;
;; Count all lines in a buffer, and display the result in the
;; minibuffer.
;;
;;
;;	.. < ls -l
;;
;; Replace the current region (or buffer in no region is selected)
;; with a directory listing of the parent directory.
;;
;;
;;	| tr -d a-z
;;
;; Delete all instances of the charachters a, b, c, ..., z, in the
;; selected region (or buffer, if no region was selected).
;;
;;
;;	... make
;;
;; Run Eshell's make (i.e. `compile') in the parent's parent
;; directory.

(eval-when-compile (require 'rx))
(require 'eshell)

;;; Code:

(defgroup shell-command+ nil
  "An extended `shell-command'"
  :group 'external
  :prefix "shell-command+-")

(defcustom shell-command+-use-eshell t
  "Check if there is an eshell-handler for each command."
  :type 'boolean)

(defconst shell-command+--command-regexp
  (rx bos
      ;; ignore all preceding whitespace
      (* space)
      ;; check for working directory string
      (? (group (or (: ?. (not (any "/"))) ?/ ?~)
                (* (not space)))
         (+ space))
      ;; check for redirection indicator
      (? (or (group ?<) (group ?>) (group ?|) ?!))
      ;; allow whitespace after indicator
      (* space)
      ;; actual command (and command name)
      (group (: (group (*? not-newline))
                (? space))
             (+ not-newline))
      eos)
  "Regular expression to parse `shell-command+' input.")

(defun shell-command+-expand-path (path)
  "Expand any PATH into absolute path with additional tricks.

Furthermore, replace each sequence with three or more `.'s with a
proper upwards directory pointers.  This means that '....' becomes
'../../../..', and so on."
  (expand-file-name
   (replace-regexp-in-string
    (rx (>= 2 "."))
    (lambda (sub)
      (mapconcat #'identity (make-list (1- (length sub)) "..") "/"))
    path)))

;;;###autoload
(defun shell-command+ (command beg end)
  "Intelligently execute string COMMAND in inferior shell.

If COMMAND is prefixed with an absolute or relative path, the
created process will the executed in the specified path.

When COMMAND starts with...
  <  the output of COMMAND replaces the current selection
  >  COMMAND is run with the current selection as input
  |  the current selection is filtered through COMMAND
  !  COMMAND is simply executed (same as without any prefix)

If `shell-command+-use-eshell' is non-nil, and the the first
argument of COMMAND has a defined `eshell'-function, use that.

Inside COMMAND, % is replaced with the current file name.  To
insert a literal % quote it using a backslash.

These extentions can all be combined with one-another.

In case a region is active, `shell-command+' will only work with the region
between BEG and END.  Otherwise the whole buffer is processed."
  (interactive (list (read-shell-command "Shell command: ")
                     (if (use-region-p) (region-beginning) (point-min))
                     (if (use-region-p) (region-end) (point-max))))
  (save-match-data
    (unless (string-match shell-command+--command-regexp command)
      (error "Invalid command"))
    (let ((path (match-string-no-properties 1 command))
          (cmd (match-string-no-properties 6 command))
          (rest (condition-case nil
                    (replace-regexp-in-string
                     (rx (* ?\\ ?\\) (or ?\\ (group "%")))
                     buffer-file-name
                     (match-string-no-properties 5 command)
                     nil nil 1)
                  (error (match-string-no-properties 5 command)))))
      (let ((default-directory (shell-command+-expand-path (or path "."))))
        (cond ((match-string-no-properties 2 command) ;<
               (delete-region beg end)
               (shell-command rest t shell-command-default-error-buffer)
               (exchange-point-and-mark))
              ((match-string-no-properties 3 command) ;>
               (shell-command-on-region
                beg end rest nil nil
                shell-command-default-error-buffer t))
              ((match-string-no-properties 4 command) ;|
               (shell-command-on-region
                beg end rest t t
                shell-command-default-error-buffer t))
              ((and shell-command+-use-eshell
                    (intern-soft (concat "eshell/" cmd)))
               (eshell-command rest (and current-prefix-arg t)))
              (t (shell-command rest (and current-prefix-arg t)
                                shell-command-default-error-buffer)))))))

(provide 'shell-command+)

;;; shell-command+.el ends here

[-- Attachment #3: Type: text/plain, Size: 611 bytes --]


> I don't see your name in the list of people with copyright assignments.
> Then again, I do see some "Philip K..." but I can't be sure it's
> indeed you.  Did you sign the paperwork already?

Yes, I signed it last year when my address was philip@warpmail.net.

>> It should also be noted, that the file is currently licensed under the
>> CC0 1.0 Universal (CC0 1.0) Public Domain Dedication[1] license, which
>> I'm not sure if it is OK.
>
> That's not a problem for us, but we'd change it to GPLv3+ when we add it
> to GNU ELPA.  Not sure if that would be OK with you.

No problem with that.

-- 
	Philip K.

  reply	other threads:[~2020-09-25 13:52 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-09-25 12:56 [ELPA] New package: shell-command+ Philip K.
2020-09-25 13:43 ` Stefan Monnier
2020-09-25 13:52   ` Philip K. [this message]
2020-09-25 23:38     ` Ergus
2020-09-26  9:38       ` Philip K.
2020-09-26 13:23         ` Ergus
2020-09-26 17:21         ` Stefan Monnier

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87zh5e0xrd.fsf@posteo.net \
    --to=philipk@posteo.net \
    --cc=emacs-devel@gnu.org \
    --cc=monnier@iro.umontreal.ca \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).